How to catch errors in React
Error Boundaries
Error boundariesIt is a feature introduced in React 16 to capture JavaScript errors that occur in its child component tree, log errors and display alternate UI instead of the entire component tree crash.
Characteristics of error boundaries:
- Only implemented through class components.
- Capture errors in rendering processes, lifecycle methods, and constructors.
- Errors in the event handler or errors in asynchronous code are not captured.
Global Error Listeners
To catch errors that are not caught by error boundaries, such as errors in event processors or errors in asynchronous code, we can use global error listeners, such asand
。
Encapsulation custom Hook captures all errors
To uniformly manage and catch all errors in React applications (including synchronization and asynchronous), we can encapsulate a custom Hook. The Hook will combine error boundaries and global error listening to achieve comprehensive error capture.
Step Overview
- Create an error context (Error Context), used to pass error messages in the application.
- Create an error provider component (ErrorProvider), set the error handling logic and provide the error status to the application.
- Create a custom Hook (useError), used to trigger error reports in any component.
- Create an error boundary component (ErrorBoundary), catch errors in component tree and pass through context.
- Use ErrorProvider and ErrorBoundary in the application root component, ensure that the entire application can catch errors.
Implement code
1. Create an ErrorContext
import React from 'react'; const ErrorContext = ({ error: null, setError: () => {}, }); export default ErrorContext;
2. Create an ErrorProvider component
import React, { useState, useEffect } from 'react'; import ErrorContext from '../context/ErrorContext'; function ErrorProvider({ children }) { const [error, setError] = useState(null); useEffect(() => { // Listen to global errors const handleError = (event) => { setError( || || ); }; ('error', handleError); ('unhandledrejection', handleError); return () => { ('error', handleError); ('unhandledrejection', handleError); }; }, []); return ( < value={{ error, setError }}> {children} </> ); } export default ErrorProvider;
3. Create a useError Hook
import { useContext } from 'react'; import ErrorContext from '../context/ErrorContext'; function useError() { const { setError } = useContext(ErrorContext); const reportError = (error) => { setError(error); ('Captured error:', error); }; return reportError; } export default useError;
4. Create an ErrorBoundary component
import React from 'react'; import ErrorContext from '../context/ErrorContext'; class ErrorBoundary extends { static contextType = ErrorContext; constructor(props) { super(props); = { hasError: false }; } componentDidCatch(error, info) { ({ hasError: true }); if ( && ) { (error); } ('ErrorBoundary caught an error:', error, info); } render() { if () { return <h1>An error occurred。</h1>; } return ; } } export default ErrorBoundary;
5. Use custom Hooks and ErrorBoundary
import React from 'react'; import ErrorProvider from './providers/ErrorProvider'; import ErrorBoundary from './components/ErrorBoundary'; import ExampleComponent from './components/ExampleComponent'; import ErrorDisplay from './components/ErrorDisplay'; function App() { return ( <ErrorProvider> <ErrorBoundary> <ExampleComponent /> </ErrorBoundary> <ErrorDisplay /> </ErrorProvider> ); } export default App;
Detailed code explanation
The implementation details of the above code will be explained step by step.
1.
Defines an error context for passing error states in the component tree.
import React from 'react'; const ErrorContext = ({ error: null, setError: () => {}, }); export default ErrorContext;
- use
Create a context with the initial value containing
error
andsetError
method. - The context allows access and updates to error status anywhere in the component tree.
2.
Create an error provider component, set up global error listening, and provide an error status.
import React, { useState, useEffect } from 'react'; import ErrorContext from '../context/ErrorContext'; function ErrorProvider({ children }) { const [error, setError] = useState(null); useEffect(() => { // Listen to global errors const handleError = (event) => { setError( || || ); }; ('error', handleError); ('unhandledrejection', handleError); return () => { ('error', handleError); ('unhandledrejection', handleError); }; }, []); return ( < value={{ error, setError }}> {children} </> ); } export default ErrorProvider;
- use
useState
manageerror
state. - use
useEffect
Add a global error listener:-
Catch synchronization errors.
-
Catch unhandled Promise errors.
-
- Remove the listener when component is uninstalled to avoid memory leaks.
- use
Will
error
andsetError
Provided to subcomponents.
3.
Create a custom Hook for reporting errors in the component.
import { useContext } from 'react'; import ErrorContext from '../context/ErrorContext'; function useError() { const { setError } = useContext(ErrorContext); const reportError = (error) => { setError(error); ('Captured error:', error); }; return reportError; } export default useError;
- use
useContext
GetsetError
method. - definition
reportError
Function for manually reporting errors. - While reporting an error, output the error message to the console.
4.
Creates a class component error boundary to capture errors that occur during rendering.
import React from 'react'; import ErrorContext from '../context/ErrorContext'; class ErrorBoundary extends { static contextType = ErrorContext; constructor(props) { super(props); = { hasError: false }; } componentDidCatch(error, info) { ({ hasError: true }); if ( && ) { (error); } ('ErrorBoundary caught an error:', error, info); } render() { if () { return <h1>An error occurred。</h1>; } return ; } } export default ErrorBoundary;
- Inherited from
, implement error boundaries.
- use
static contextType
Get the context. - exist
componentDidCatch
In the method:- Update local status
hasError
。 - Through context
setError
Method reports an error. - Output the error message to the console.
- Update local status
- If an error occurs, render the backup UI.
5.
Use in the root component of the applicationErrorProvider
andErrorBoundary
, ensure that the entire application can catch errors.
import React from 'react'; import ErrorProvider from './providers/ErrorProvider'; import ErrorBoundary from './components/ErrorBoundary'; import ExampleComponent from './components/ExampleComponent'; import ErrorDisplay from './components/ErrorDisplay'; function App() { return ( <ErrorProvider> <ErrorBoundary> <ExampleComponent /> </ErrorBoundary> <ErrorDisplay /> </ErrorProvider> ); } export default App;
-
ErrorProvider
Package the entire application and provide error status. -
ErrorBoundary
Package specific business components, such asExampleComponent
。 -
ErrorDisplay
Components are used to display error messages.
6.
An example component for triggering synchronous and asynchronous errors, testing the error capture mechanism.
import React from 'react'; import useError from '../hooks/useError'; function ExampleComponent() { const reportError = useError(); const handleSyncError = () => { throw new Error('Synchronous Error Example'); }; const handleAsyncError = async () => { try { await (new Error('Async Error Example')); } catch (error) { reportError(error); } }; return ( <div> <h2>Sample Components</h2> <button onClick={handleSyncError}>Trigger synchronization error</button> <button onClick={handleAsyncError}>Trigger an asynchronous error</button> </div> ); } export default ExampleComponent;
- Two buttons are provided to trigger synchronization and asynchronous errors respectively.
- Synchronization error is thrown directly
Error
accomplish. - Asynchronous error is returned by returning a rejected Promise and in
catch
Used inreportError
Report an error.
7.
A component that displays the currently captured error message.
import React, { useContext } from 'react'; import ErrorContext from '../context/ErrorContext'; function ErrorDisplay() { const { error } = useContext(ErrorContext); if (!error) return null; return ( <div style={{ background: 'red', color: 'white', padding: '10px' }}> <h3>Global Error Catch:</h3> <p>{()}</p> </div> ); } export default ErrorDisplay;
- use
useContext
Get the current error status. - If there is an error, render the error message.
Summarize
This article details a variety of ways to catch errors in React, including error boundaries and global error listening, and shows how to encapsulate a custom Hook to manage and capture all synchronous and asynchronous errors. This centralized error handling mechanism helps improve the stability and maintenance of the application, allowing developers to more conveniently monitor and handle errors and improve user experience.
Through the above implementation, developers can easily catch and handle various errors in React applications, whether they occur during rendering, in lifecycle methods, or in asynchronous operations. This provides strong support for building robust and reliable React applications.
The above is the detailed content of the implementation method of React encapsulation custom Hook to capture all errors. For more information about React Hook to capture all errors, please follow my other related articles!