Reactã«ãããå ç¢ãªãšã©ãŒãã³ããªã³ã°ãšåªé ãªUIãã°ã©ããŒã·ã§ã³ã®ããã®ãJavaScriptãšã©ãŒããŠã³ããªãŒã®çè§£ãšå®è£ ã«é¢ããå æ¬çã¬ã€ãã
JavaScriptãšã©ãŒããŠã³ããªãŒïŒReactãšã©ãŒãã³ããªã³ã°å®è£ ã¬ã€ã
Reactéçºã®äžçã§ã¯ãäºæãã¬ãšã©ãŒããŠãŒã¶ãŒäœéšãæãªããã¢ããªã±ãŒã·ã§ã³ã®äžå®å®æ§ãåŒãèµ·ããå¯èœæ§ããããŸããå ç¢ã§ä¿¡é Œæ§ã®é«ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããã«ã¯ãæç¢ºã«å®çŸ©ããããšã©ãŒãã³ããªã³ã°æŠç¥ãäžå¯æ¬ ã§ããReactã®ãšã©ãŒããŠã³ããªãŒã¯ãã³ã³ããŒãã³ãããªãŒå ã§çºçãããšã©ãŒãåªé ã«åŠçããã¢ããªã±ãŒã·ã§ã³å šäœãã¯ã©ãã·ã¥ããã®ãé²ãããã©ãŒã«ããã¯UIã衚瀺ããããã®åŒ·åãªã¡ã«ããºã ãæäŸããŸãã
ãšã©ãŒããŠã³ããªãŒãšã¯ïŒ
ãšã©ãŒããŠã³ããªãŒã¯ããã®åã³ã³ããŒãã³ãããªãŒå ã®ã©ããã§çºçããJavaScriptãšã©ãŒããã£ãããããããã®ãšã©ãŒããã°ã«èšé²ããã¯ã©ãã·ã¥ããã³ã³ããŒãã³ãããªãŒã®ä»£ããã«ãã©ãŒã«ããã¯UIã衚瀺ããReactã³ã³ããŒãã³ãã§ãããšã©ãŒããŠã³ããªãŒã¯ãã¬ã³ããªã³ã°äžãã©ã€ããµã€ã¯ã«ã¡ãœããå ãããã³ãã®äžã®ããªãŒå šäœã®ã³ã³ã¹ãã©ã¯ã¿ã§ãšã©ãŒããã£ããããŸãã
ãšã©ãŒããŠã³ããªãŒã¯ãReactã³ã³ããŒãã³ãã®ããã®try...catch
ãããã¯ã®ãããªãã®ã ãšèããŠãã ãããtry...catch
ãããã¯ãåæçãªJavaScriptã³ãŒãã§äŸå€ãåŠçã§ããããã«ããšã©ãŒããŠã³ããªãŒã¯Reactã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°äžã«çºçãããšã©ãŒãåŠçã§ããããã«ããŸãã
éèŠãªæ³šæç¹ïŒãšã©ãŒããŠã³ããªãŒã¯ã以äžã®ãšã©ãŒããã£ããããŸããïŒ
- ã€ãã³ããã³ãã©ãŒïŒè©³çްã¯åŸè¿°ïŒ
- éåæã³ãŒãïŒäŸïŒ
setTimeout
ãrequestAnimationFrame
ã®ã³ãŒã«ããã¯ïŒ - ãµãŒããŒãµã€ãã¬ã³ããªã³ã°
- ãšã©ãŒããŠã³ããªãŒèªäœïŒãã®åã§ã¯ãªãïŒã§ã¹ããŒããããšã©ãŒ
ãªããšã©ãŒããŠã³ããªãŒã䜿çšããã®ãïŒ
ãšã©ãŒããŠã³ããªãŒã䜿çšããããšã«ã¯ãããã€ãã®éèŠãªå©ç¹ããããŸãïŒ
- ãŠãŒã¶ãŒäœéšã®åäžïŒçã£çœãªç»é¢ãäžå¯è§£ãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ãã代ããã«ããŠãŒã¶ãŒãã¬ã³ããªãŒãªãã©ãŒã«ããã¯UIã衚瀺ã§ããŸããããã«ããããŠãŒã¶ãŒã«äœããããŸããããªãã£ãããšãäŒããå埩ããæ¹æ³ïŒäŸïŒããŒãžã®åèªã¿èŸŒã¿ãå¥ã®ã»ã¯ã·ã§ã³ãžã®ç§»åïŒãææ¡ããããšãã§ããŸãã
- ã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§ïŒãšã©ãŒããŠã³ããªãŒã¯ãã¢ããªã±ãŒã·ã§ã³ã®äžéšã§çºçãããšã©ãŒãã¢ããªã±ãŒã·ã§ã³å šäœãã¯ã©ãã·ã¥ãããã®ãé²ããŸããããã¯ãå€ãã®çžäºæ¥ç¶ãããã³ã³ããŒãã³ããæã€è€éãªã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠç¹ã«éèŠã§ãã
- äžå åããããšã©ãŒãã³ããªã³ã°ïŒãšã©ãŒããŠã³ããªãŒã¯ããšã©ãŒããã°ã«èšé²ããåé¡ã®æ ¹æ¬åå ã远跡ããããã®äžå çãªå ŽæãæäŸããŸããããã«ããããããã°ãšã¡ã³ããã³ã¹ãç°¡çŽ åãããŸãã
- åªé ãªãã°ã©ããŒã·ã§ã³ïŒã¢ããªã±ãŒã·ã§ã³ã®ããŸããŸãªéšåã«æŠç¥çã«ãšã©ãŒããŠã³ããªãŒãé 眮ããããšã§ãäžéšã®ã³ã³ããŒãã³ãã倱æããŠããã¢ããªã±ãŒã·ã§ã³ã®æ®ãã®éšåãæ©èœãç¶ããããã«ã§ããŸããããã«ããããšã©ãŒã«çŽé¢ããŠãåªé ãªãã°ã©ããŒã·ã§ã³ãå¯èœã«ãªããŸãã
Reactã§ã®ãšã©ãŒããŠã³ããªãŒã®å®è£
ãšã©ãŒããŠã³ããªãŒãäœæããã«ã¯ã以äžã®ã©ã€ããµã€ã¯ã«ã¡ãœããã®ããããïŒãŸãã¯äž¡æ¹ïŒãå®è£ ããã¯ã©ã¹ã³ã³ããŒãã³ããå®çŸ©ããå¿ èŠããããŸãïŒ
static getDerivedStateFromError(error)
ïŒãã®ã©ã€ããµã€ã¯ã«ã¡ãœããã¯ãåå«ã³ã³ããŒãã³ãã«ãã£ãŠãšã©ãŒãã¹ããŒãããåŸã«åŒã³åºãããŸããã¹ããŒããããšã©ãŒãåŒæ°ãšããŠåãåããã³ã³ããŒãã³ãã®stateãæŽæ°ããŠãšã©ãŒãçºçããããšã瀺ãå€ïŒäŸïŒhasError
ãã©ã°ãtrue
ã«èšå®ããïŒãè¿ãã¹ãã§ããcomponentDidCatch(error, info)
ïŒãã®ã©ã€ããµã€ã¯ã«ã¡ãœããã¯ãåå«ã³ã³ããŒãã³ãã«ãã£ãŠãšã©ãŒãã¹ããŒãããåŸã«åŒã³åºãããŸããã¹ããŒããããšã©ãŒãåŒæ°ãšããŠåãåããã©ã®ã³ã³ããŒãã³ãããšã©ãŒãã¹ããŒãããã«é¢ããæ å ±ãå«ãinfo
ãªããžã§ã¯ããåãåããŸãããã®ã¡ãœããã䜿çšããŠãSentryãBugsnagãªã©ã®ãµãŒãã¹ã«ãšã©ãŒããã°èšé²ã§ããŸãã
以äžã¯ããšã©ãŒããŠã³ããªãŒã³ã³ããŒãã³ãã®åºæ¬çãªäŸã§ãïŒ
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null
};
}
static getDerivedStateFromError(error) {
// 次ã®ã¬ã³ããªã³ã°ã§ãã©ãŒã«ããã¯UIã衚瀺ãããããã«stateãæŽæ°ããŸãã
return {
hasError: true,
error: error
};
}
componentDidCatch(error, info) {
// "componentStack"ã®äŸïŒ
// in ComponentThatThrows (created by App)
// in MyErrorBoundary (created by App)
// in div (created by App)
// in App
console.error("Caught an error:", error, info);
this.setState({
errorInfo: info.componentStack
});
// ãšã©ãŒå ±åãµãŒãã¹ã«ãšã©ãŒããã°èšé²ããããšãã§ããŸã
//logErrorToMyService(error, info.componentStack);
}
render() {
if (this.state.hasError) {
// ä»»æã®ã«ã¹ã¿ã ãã©ãŒã«ããã¯UIãã¬ã³ããªã³ã°ã§ããŸã
return (
<div>
<h2>äœããããŸããããŸããã§ããã</h2>
<p>ãšã©ãŒ: {this.state.error ? this.state.error.message : "äžæãªãšã©ãŒãçºçããŸããã"}</p>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.errorInfo && this.state.errorInfo}
</details>
</div>
);
}
return this.props.children;
}
}
ãšã©ãŒããŠã³ããªãŒã䜿çšããã«ã¯ãä¿è·ãããã³ã³ããŒãã³ãããªãŒãã©ããããã ãã§ãïŒ
<ErrorBoundary>
<MyComponentThatMightThrow/>
</ErrorBoundary>
ãšã©ãŒããŠã³ããªãŒäœ¿çšã®å®è·µäŸ
ãšã©ãŒããŠã³ããªãŒãç¹ã«åœ¹ç«ã€å®è·µçãªã·ããªãªãããã€ãèŠãŠã¿ãŸãããïŒ
1. APIãšã©ãŒã®åŠç
APIããããŒã¿ããã§ããããéããããã¯ãŒã¯ã®åé¡ããµãŒããŒã®åé¡ããŸãã¯ç¡å¹ãªããŒã¿ã«ãã£ãŠãšã©ãŒãçºçããå¯èœæ§ããããŸããããŒã¿ããã§ããããŠè¡šç€ºããã³ã³ããŒãã³ãããšã©ãŒããŠã³ããªãŒã§ã©ããããããšã§ããããã®ãšã©ãŒãåªé ã«åŠçã§ããŸãã
function UserProfile() {
const [user, setUser] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
async function fetchData() {
try {
const response = await fetch('/api/user');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (error) {
// ãšã©ãŒã¯ErrorBoundaryã«ãã£ãŠãã£ãããããŸã
throw error;
} finally {
setIsLoading(false);
}
}
fetchData();
}, []);
if (isLoading) {
return <p>ãŠãŒã¶ãŒãããã¡ã€ã«ãèªã¿èŸŒã¿äž...</p>;
}
if (!user) {
return <p>ãŠãŒã¶ãŒããŒã¿ããããŸããã</p>;
}
return (
<div>
<h2>{user.name}</h2>
<p>Email: {user.email}</p>
</div>
);
}
function App() {
return (
<ErrorBoundary>
<UserProfile />
</ErrorBoundary>
);
}
ãã®äŸã§ã¯ãAPIåŒã³åºãã倱æããããšã©ãŒãè¿ãããããå Žåããšã©ãŒããŠã³ããªãŒããšã©ãŒããã£ãããããã©ãŒã«ããã¯UIïŒãšã©ãŒããŠã³ããªãŒã®render
ã¡ãœããå
ã§å®çŸ©ïŒã衚瀺ããŸããããã«ãããã¢ããªã±ãŒã·ã§ã³å
šäœãã¯ã©ãã·ã¥ããã®ãé²ãããŠãŒã¶ãŒã«ããæçãªã¡ãã»ãŒãžãæäŸããŸãããã©ãŒã«ããã¯UIãæ¡åŒµããŠããªã¯ãšã¹ããå詊è¡ãããªãã·ã§ã³ãæäŸããããšãã§ããŸãã
2. ãµãŒãããŒãã£ã©ã€ãã©ãªãšã©ãŒã®åŠç
ãµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããŠããå Žåãããããäºæããªããšã©ãŒãã¹ããŒããå¯èœæ§ããããŸãããããã®ã©ã€ãã©ãªã䜿çšããã³ã³ããŒãã³ãããšã©ãŒããŠã³ããªãŒã§ã©ããããããšã§ããããã®ãšã©ãŒãåªé ã«åŠçããã®ã«åœ¹ç«ã¡ãŸãã
ããŒã¿ã®äžæŽåããã®ä»ã®åé¡ã«ãããæã ãšã©ãŒãã¹ããŒããæ¶ç©ºã®ãã£ãŒãã©ã€ãã©ãªãèããŠã¿ãŸããããæ¬¡ã®ããã«ãã£ãŒãã³ã³ããŒãã³ããã©ããã§ããŸãïŒ
function MyChartComponent() {
try {
// ãµãŒãããŒãã£ã©ã€ãã©ãªã䜿çšããŠãã£ãŒããã¬ã³ããªã³ã°
return <Chart data={data} />;
} catch (error) {
// ãã®catchãããã¯ã¯Reactã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ãšã©ãŒã«ã¯å¹æããããŸãã
// äž»ã«ãã®ç¹å®ã®é¢æ°å
ã®åæãšã©ãŒçšã§ãã
console.error("Error rendering chart:", error);
// ErrorBoundaryã«ãã£ãããããããã«ãšã©ãŒãã¹ããŒããããšãæ€èšããŠãã ãã
throw error; // ãšã©ãŒãåã¹ããŒ
}
}
function App() {
return (
<ErrorBoundary>
<MyChartComponent />
</ErrorBoundary>
);
}
Chart
ã³ã³ããŒãã³ãããšã©ãŒãã¹ããŒããå Žåããšã©ãŒããŠã³ããªãŒãããããã£ããããŠãã©ãŒã«ããã¯UIã衚瀺ããŸããMyChartComponentå
ã®try/catchã¯ãã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ã§ã¯ãªããåæé¢æ°å
ã®ãšã©ãŒã®ã¿ããã£ããããããšã«æ³šæããŠãã ããããããã£ãŠãããã§ã¯ãšã©ãŒããŠã³ããªãŒãéåžžã«éèŠã§ãã
3. ã¬ã³ããªã³ã°ãšã©ãŒã®åŠç
ç¡å¹ãªããŒã¿ãäžæ£ãªpropã®åããã®ä»ã®åé¡ã«ãããã¬ã³ããªã³ã°ããã»ã¹äžã«ãšã©ãŒãçºçããããšããããŸãããšã©ãŒããŠã³ããªãŒã¯ãããã®ãšã©ãŒããã£ããããã¢ããªã±ãŒã·ã§ã³ãã¯ã©ãã·ã¥ããã®ãé²ãããšãã§ããŸãã
function DisplayName({ name }) {
if (typeof name !== 'string') {
throw new Error('Name must be a string');
}
return <h2>Hello, {name}!</h2>;
}
function App() {
return (
<ErrorBoundary>
<DisplayName name={123} /> <!-- äžæ£ãªpropã®å -->
</ErrorBoundary>
);
}
ãã®äŸã§ã¯ãDisplayName
ã³ã³ããŒãã³ãã¯name
ããããã£ãæååã§ããããšãæåŸ
ããŠããŸãã代ããã«æ°å€ãæž¡ããããšããšã©ãŒãã¹ããŒããããšã©ãŒããŠã³ããªãŒãããããã£ããããŠãã©ãŒã«ããã¯UIã衚瀺ããŸãã
ãšã©ãŒããŠã³ããªãŒãšã€ãã³ããã³ãã©ãŒ
åè¿°ã®éãããšã©ãŒããŠã³ããªãŒã¯ã€ãã³ããã³ãã©ãŒå ã§çºçãããšã©ãŒããã£ããããŸãããããã¯ãã€ãã³ããã³ãã©ãŒãéåžžéåæã§ããããšã©ãŒããŠã³ããªãŒã¯ã¬ã³ããªã³ã°äžãã©ã€ããµã€ã¯ã«ã¡ãœããå ãããã³ã³ã³ã¹ãã©ã¯ã¿ã§çºçãããšã©ãŒã®ã¿ããã£ããããããã§ãã
ã€ãã³ããã³ãã©ãŒã§ãšã©ãŒãåŠçããã«ã¯ãã€ãã³ããã³ãã©ãŒé¢æ°å
ã§åŸæ¥ã®try...catch
ãããã¯ã䜿çšããå¿
èŠããããŸãã
function MyComponent() {
const handleClick = () => {
try {
// ãšã©ãŒãã¹ããŒããå¯èœæ§ã®ããã³ãŒã
throw new Error('An error occurred in the event handler');
} catch (error) {
console.error('Caught an error in the event handler:', error);
// ãšã©ãŒãåŠçããïŒäŸïŒãŠãŒã¶ãŒã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããïŒ
}
};
return <button onClick={handleClick}>Click Me</button>;
}
ã°ããŒãã«ãšã©ãŒãã³ããªã³ã°
ãšã©ãŒããŠã³ããªãŒã¯Reactã³ã³ããŒãã³ãããªãŒå ã®ãšã©ãŒãåŠçããã®ã«åªããŠããŸããããã¹ãŠã®ãšã©ãŒã·ããªãªãã«ããŒããŠããããã§ã¯ãããŸãããããšãã°ãã°ããŒãã«ãªã€ãã³ããªã¹ããŒã§ã®ãšã©ãŒããReactãåæåãããåã«å®è¡ãããã³ãŒãã§ã®ãšã©ãŒãªã©ãReactã³ã³ããŒãã³ãã®å€éšã§çºçãããšã©ãŒã¯ãã£ããããŸããã
ãããã®ã¿ã€ãã®ãšã©ãŒãåŠçããã«ã¯ãwindow.onerror
ã€ãã³ããã³ãã©ãŒã䜿çšã§ããŸãã
window.onerror = function(message, source, lineno, colno, error) {
console.error('Global error handler:', message, source, lineno, colno, error);
// SentryãBugsnagãªã©ã®ãµãŒãã¹ã«ãšã©ãŒããã°èšé²ãã
// ãŠãŒã¶ãŒã«ã°ããŒãã«ãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ããïŒä»»æïŒ
return true; // ããã©ã«ãã®ãšã©ãŒåŠçåäœãé²ã
};
window.onerror
ã€ãã³ããã³ãã©ãŒã¯ããã£ãããããªãã£ãJavaScriptãšã©ãŒãçºçãããã³ã«åŒã³åºãããŸããããã䜿çšããŠããšã©ãŒããã°ã«èšé²ãããããŠãŒã¶ãŒã«ã°ããŒãã«ãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ãããããšã©ãŒãåŠçããããã®ä»ã®ã¢ã¯ã·ã§ã³ãå®è¡ãããã§ããŸãã
éèŠïŒwindow.onerror
ã€ãã³ããã³ãã©ãŒããtrue
ãè¿ããšããã©ãŠã¶ãããã©ã«ãã®ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããã®ãé²ããŸãããã ãããŠãŒã¶ãŒäœéšã«æ³šæããŠãã ãããããã©ã«ãã®ã¡ãã»ãŒãžãæå¶ããå Žåã¯ãæç¢ºã§æçãªä»£æ¿ææ®µãæäŸããããã«ããŠãã ããã
ãšã©ãŒããŠã³ããªãŒã䜿çšããããã®ãã¹ããã©ã¯ãã£ã¹
ãšã©ãŒããŠã³ããªãŒã䜿çšããéã«çæãã¹ããã¹ããã©ã¯ãã£ã¹ãããã€ã玹ä»ããŸãïŒ
- ãšã©ãŒããŠã³ããªãŒãæŠç¥çã«é 眮ããïŒã¢ããªã±ãŒã·ã§ã³ã®ããŸããŸãªéšåããšã©ãŒããŠã³ããªãŒã§ã©ããããŠãšã©ãŒãåé¢ãããšã©ãŒãé£éããã®ãé²ããŸããã«ãŒãå šäœãUIã®äž»èŠãªã»ã¯ã·ã§ã³ãã©ããããããšãæ€èšããŠãã ããã
- æçãªãã©ãŒã«ããã¯UIãæäŸããïŒãã©ãŒã«ããã¯UIã¯ããšã©ãŒãçºçããããšããŠãŒã¶ãŒã«ç¥ãããå埩ããæ¹æ³ãææ¡ããå¿ èŠããããŸãããäœããããŸããããŸããã§ãããã®ãããªäžè¬çãªãšã©ãŒã¡ãã»ãŒãžã®è¡šç€ºã¯é¿ããŠãã ããã
- ãšã©ãŒããã°ã«èšé²ããïŒ
componentDidCatch
ã©ã€ããµã€ã¯ã«ã¡ãœããã䜿çšããŠãSentryãBugsnagãªã©ã®ãµãŒãã¹ã«ãšã©ãŒããã°ã«èšé²ããŸããããã«ãããåé¡ã®æ ¹æ¬åå ã远跡ããã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§ãåäžãããããšãã§ããŸãã - äºæããããšã©ãŒã«ãšã©ãŒããŠã³ããªãŒã䜿çšããªãïŒãšã©ãŒããŠã³ããªãŒã¯äºæããªããšã©ãŒãåŠçããããã«èšèšãããŠããŸããäºæããããšã©ãŒïŒäŸïŒããªããŒã·ã§ã³ãšã©ãŒãAPIãšã©ãŒïŒã«ã¯ã
try...catch
ãããã¯ãã«ã¹ã¿ã ãšã©ãŒãã³ããªã³ã°ã³ã³ããŒãã³ããªã©ãããå ·äœçãªãšã©ãŒãã³ããªã³ã°ã¡ã«ããºã ã䜿çšããŠãã ããã - è€æ°ã¬ãã«ã®ãšã©ãŒããŠã³ããªãŒãæ€èšããïŒãšã©ãŒããŠã³ããªãŒããã¹ãããŠãããŸããŸãªã¬ãã«ã®ãšã©ãŒãã³ããªã³ã°ãæäŸã§ããŸããããšãã°ãæªåŠçã®ãšã©ãŒããã£ããããŠäžè¬çãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ããã°ããŒãã«ãªãšã©ãŒããŠã³ããªãŒãšãç¹å®ã®ã³ã³ããŒãã³ãã®ãšã©ãŒããã£ããããŠãã詳现ãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ãããããå ·äœçãªãšã©ãŒããŠã³ããªãŒãæã€ããšãã§ããŸãã
- ãµãŒããŒãµã€ãã¬ã³ããªã³ã°ãå¿ããªãïŒãµãŒããŒãµã€ãã¬ã³ããªã³ã°ã䜿çšããŠããå Žåã¯ããµãŒããŒåŽã§ããšã©ãŒãåŠçããå¿ èŠããããŸãããšã©ãŒããŠã³ããªãŒã¯ãµãŒããŒäžã§æ©èœããŸãããååã¬ã³ããªã³ã°äžã«çºçãããšã©ãŒããã£ããããããã«è¿œå ã®ãšã©ãŒãã³ããªã³ã°ã¡ã«ããºã ã䜿çšããå¿ èŠããããããããŸããã
é«åºŠãªãšã©ãŒããŠã³ããªãŒãã¯ããã¯
1. ã¬ã³ããŒããããã®äœ¿çš
éçãªãã©ãŒã«ããã¯UIãã¬ã³ããªã³ã°ãã代ããã«ãã¬ã³ããŒããããã䜿çšããŠããšã©ãŒã®åŠçæ¹æ³ã«æè»æ§ãæãããããšãã§ããŸããã¬ã³ããŒããããã¯ãã³ã³ããŒãã³ããäœããã¬ã³ããªã³ã°ããããã«äœ¿çšãã颿°ããããã£ã§ãã
class ErrorBoundary extends React.Component {
// ... (以åãšåã)
render() {
if (this.state.hasError) {
// ã¬ã³ããŒããããã䜿çšããŠãã©ãŒã«ããã¯UIãã¬ã³ããªã³ã°
return this.props.fallbackRender(this.state.error, this.state.errorInfo);
}
return this.props.children;
}
}
function App() {
return (
<ErrorBoundary fallbackRender={(error, errorInfo) => (
<div>
<h2>äœããããŸããããŸããã§ããïŒ</h2>
<p>ãšã©ãŒ: {error.message}</p>
<details style={{ whiteSpace: 'pre-wrap' }}>
{errorInfo.componentStack}
</details>
</div>
)}>
<MyComponentThatMightThrow/>
</ErrorBoundary>
);
}
ããã«ããããšã©ãŒããŠã³ããªãŒããšã«ãã©ãŒã«ããã¯UIãã«ã¹ã¿ãã€ãºã§ããŸããfallbackRender
ããããã¯ãšã©ãŒãšãšã©ãŒæ
å ±ãåŒæ°ãšããŠåãåããããããå
·äœçãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ãããããšã©ãŒã«åºã¥ããŠä»ã®ã¢ã¯ã·ã§ã³ãå®è¡ãããã§ããŸãã
2. é«éã³ã³ããŒãã³ãïŒHOCïŒãšããŠã®ãšã©ãŒããŠã³ããªãŒ
å¥ã®ã³ã³ããŒãã³ãããšã©ãŒããŠã³ããªãŒã§ã©ããããé«éã³ã³ããŒãã³ãïŒHOCïŒãäœæã§ããŸããããã¯ãåãã³ãŒããç¹°ãè¿ãããšãªããè€æ°ã®ã³ã³ããŒãã³ãã«ãšã©ãŒããŠã³ããªãŒãé©çšããã®ã«åœ¹ç«ã¡ãŸãã
function withErrorBoundary(WrappedComponent) {
return class WithErrorBoundary extends React.Component {
render() {
return (
<ErrorBoundary>
<WrappedComponent {...this.props} />
</ErrorBoundary>
);
}
};
}
// äœ¿çšæ³:
const MyComponentWithErrorHandling = withErrorBoundary(MyComponentThatMightThrow);
withErrorBoundary
颿°ã¯ã³ã³ããŒãã³ããåŒæ°ãšããŠåãåããå
ã®ã³ã³ããŒãã³ãããšã©ãŒããŠã³ããªãŒã§ã©ããããæ°ããã³ã³ããŒãã³ããè¿ããŸããããã«ãããã¢ããªã±ãŒã·ã§ã³ã®ã©ã®ã³ã³ããŒãã³ãã«ãç°¡åã«ãšã©ãŒãã³ããªã³ã°ã远å ã§ããŸãã
ãšã©ãŒããŠã³ããªãŒã®ãã¹ã
ãšã©ãŒããŠã³ããªãŒãæ£ããæ©èœããŠããããšã確èªããããã«ããã¹ãããããšãéèŠã§ããJestãReact Testing Libraryã®ãããªãã¹ãã©ã€ãã©ãªã䜿çšããŠããšã©ãŒããŠã³ããªãŒããã¹ãã§ããŸãã
以äžã¯ãReact Testing Libraryã䜿çšããŠãšã©ãŒããŠã³ããªãŒããã¹ãããæ¹æ³ã®äŸã§ãïŒ
import { render, screen, fireEvent } from '@testing-library/react';
import ErrorBoundary from './ErrorBoundary';
function ComponentThatThrows() {
throw new Error('This component throws an error');
}
test('renders fallback UI when an error is thrown', () => {
render(
<ErrorBoundary>
<ComponentThatThrows />
</ErrorBoundary>
);
expect(screen.getByText('äœããããŸããããŸããã§ããã')).toBeInTheDocument();
});
ãã®ãã¹ãã¯ãšã©ãŒãã¹ããŒããComponentThatThrows
ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããŸããæ¬¡ã«ããã¹ãã¯ãšã©ãŒããŠã³ããªãŒã«ãã£ãŠã¬ã³ããªã³ã°ããããã©ãŒã«ããã¯UIã衚瀺ãããããšãã¢ãµãŒãããŸãã
ãšã©ãŒããŠã³ããªãŒãšãµãŒããŒã³ã³ããŒãã³ãïŒReact 18以éïŒ
React 18以éã§ã®ãµãŒããŒã³ã³ããŒãã³ãã®å°å ¥ã«äŒŽãããšã©ãŒããŠã³ããªãŒã¯ãšã©ãŒãã³ããªã³ã°ã«ãããŠåŒãç¶ãéèŠãªåœ¹å²ãæãããŸãããµãŒããŒã³ã³ããŒãã³ãã¯ãµãŒããŒäžã§å®è¡ãããã¬ã³ããªã³ã°ãããåºåã®ã¿ãã¯ã©ã€ã¢ã³ãã«éä¿¡ããŸããæ žãšãªãååã¯åãã§ãããèæ ®ãã¹ãããã€ãã®ãã¥ã¢ã³ã¹ããããŸãïŒ
- ãµãŒããŒãµã€ãã®ãšã©ãŒãã°èšé²ïŒãµãŒããŒã³ã³ããŒãã³ãå ã§çºçãããšã©ãŒããµãŒããŒäžã§ãã°ã«èšé²ããŠããããšã確èªããŠãã ãããããã«ã¯ããµãŒããŒãµã€ãã®ãã®ã³ã°ãã¬ãŒã ã¯ãŒã¯ã䜿çšãããããšã©ãŒãã©ããã³ã°ãµãŒãã¹ã«ãšã©ãŒãéä¿¡ãããããããšãå«ãŸããå ŽåããããŸãã
- ã¯ã©ã€ã¢ã³ããµã€ãã®ãã©ãŒã«ããã¯ïŒãµãŒããŒã³ã³ããŒãã³ãã¯ãµãŒããŒã§ã¬ã³ããªã³ã°ãããŸããããšã©ãŒã®å Žåã«åããŠã¯ã©ã€ã¢ã³ããµã€ãã®ãã©ãŒã«ããã¯UIãæäŸããå¿ èŠããããŸããããã«ããããµãŒããŒãã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°ã«å€±æããå Žåã§ãããŠãŒã¶ãŒã¯äžè²«ããäœéšãåŸãããšãã§ããŸãã
- ã¹ããªãŒãã³ã°SSRïŒã¹ããªãŒãã³ã°ãµãŒããŒãµã€ãã¬ã³ããªã³ã°ïŒSSRïŒã䜿çšããŠããå Žåãã¹ããªãŒãã³ã°ããã»ã¹äžã«ãšã©ãŒãçºçããå¯èœæ§ããããŸãããšã©ãŒããŠã³ããªãŒã¯ã圱é¿ãåããã¹ããªãŒã ã®ãã©ãŒã«ããã¯UIãã¬ã³ããªã³ã°ããããšã§ããããã®ãšã©ãŒãåªé ã«åŠçããã®ã«åœ¹ç«ã¡ãŸãã
ãµãŒããŒã³ã³ããŒãã³ãã§ã®ãšã©ãŒãã³ããªã³ã°ã¯é²åããŠããåéãªã®ã§ãææ°ã®ãã¹ããã©ã¯ãã£ã¹ãæšå¥šäºé ãåžžã«ææ¡ããŠããããšãéèŠã§ãã
é¿ããã¹ãäžè¬çãªèœãšã穎
- ãšã©ãŒããŠã³ããªãŒãžã®é床ãªäŸåïŒã³ã³ããŒãã³ãå ã®é©åãªãšã©ãŒãã³ããªã³ã°ã®ä»£ãããšããŠãšã©ãŒããŠã³ããªãŒã䜿çšããªãã§ãã ãããåžžã«ããšã©ãŒãåªé ã«åŠçããå ç¢ã§ä¿¡é Œæ§ã®é«ãã³ãŒããæžãããåªããŠãã ããã
- ãšã©ãŒã®ç¡èŠïŒãšã©ãŒããŠã³ããªãŒã«ãã£ãŠãã£ããããããšã©ãŒã¯å¿ ããã°ã«èšé²ããåé¡ã®æ ¹æ¬åå ã远跡ã§ããããã«ããŠãã ãããåã«ãã©ãŒã«ããã¯UIã衚瀺ããŠãšã©ãŒãç¡èŠããªãã§ãã ããã
- ããªããŒã·ã§ã³ãšã©ãŒãžã®ãšã©ãŒããŠã³ããªãŒã®äœ¿çšïŒãšã©ãŒããŠã³ããªãŒã¯ããªããŒã·ã§ã³ãšã©ãŒãåŠçããããã®é©åãªããŒã«ã§ã¯ãããŸããã代ããã«ãããå ·äœçãªããªããŒã·ã§ã³æè¡ã䜿çšããŠãã ããã
- ãšã©ãŒããŠã³ããªãŒã®ãã¹ããããªãïŒãšã©ãŒããŠã³ããªãŒãæ£ããæ©èœããŠããããšã確èªããããã«ãã¹ãããŠãã ããã
çµè«
ãšã©ãŒããŠã³ããªãŒã¯ãå ç¢ã§ä¿¡é Œæ§ã®é«ãReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®åŒ·åãªããŒã«ã§ãããšã©ãŒããŠã³ããªãŒã广çã«å®è£ ãã䜿çšããæ¹æ³ãçè§£ããããšã§ããŠãŒã¶ãŒäœéšãåäžãããã¢ããªã±ãŒã·ã§ã³ã®ã¯ã©ãã·ã¥ãé²ãããããã°ãç°¡çŽ åã§ããŸãããšã©ãŒããŠã³ããªãŒãæŠç¥çã«é 眮ããæçãªãã©ãŒã«ããã¯UIãæäŸãããšã©ãŒããã°ã«èšé²ãããšã©ãŒããŠã³ããªãŒã培åºçã«ãã¹ãããããšãå¿ããªãã§ãã ããã
ãã®ã¬ã€ãã§æŠèª¬ããã¬ã€ãã©ã€ã³ãšãã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãReactã¢ããªã±ãŒã·ã§ã³ããšã©ãŒã«å¯ŸããŠå埩åãããããŠãŒã¶ãŒã«è¯å®çãªäœéšãæäŸã§ããããã«ãªããŸãã