Hello everyone, I'm Casson.
In many comprehensive use Hooks
development team, the only use ClassComponent
scene is to use ClassComponent to create ErrorBoundary .
It can be said that if Hooks
there are alternatives to the following two lifecycle functions, it can completely abandon ClassComponent
:
- getDerivedStateFromError
- componentDidCatch
Then why hasn't the target Hook
yet?
Today we will discuss this issue from the implementation principles of the above two life cycle functions and the cost of porting to Hook
.
Welcome to join the human high-quality front-end framework group , with flying
ErrorBoundary implementation principle
ErrorBoundary
can catch errors within React workflows in descendant components.
React workflow refers to:
- The render stage, that is, the stage where the component render and Diff algorithm occur
- The commit stage is the stage where the DOM is rendered and the componentDidMount/Update is executed
This is also why errors that occur in event callbacks cannot be caught ErrorBoundary
event callbacks are not part of the React workflow .
How to catch errors
The overall execution flow of the render phase is as follows:
do {
try {
// render阶段具体的执行流程
workLoop();
break;
} catch (thrownValue) {
handleError(root, thrownValue);
}
} while (true);
It can be found that if an error occurs in the render stage , it will be captured and executed handleError
method.
Similarly, the overall execution flow of the commit phase is as follows:
try {
// ...具体执行流程
} catch (error) {
captureCommitPhaseError(current, nearestMountedAncestor, error);
}
If an error occurs in the commit phase , it will be caught and executed captureCommitPhaseError
method.
getDerivedStateFromError principle
How to deal with the error after catching it?
We know that the first parameter of ClassComponent
in this.setState
can receive not only a new state , but also a function that changes the state as a parameter:
// 可以这样
this.setState(this.state.num + 1)
// 也可以这样
this.setState(num => num + 1)
The realization of getDerivedStateFromError
this.setState
on the feature of the function that changes the state in ---dcfbf84c5967beb9ba43a57e78f733a1---.
When the error is caught, that is:
- For the render stage ,
handleError
after execution - For the commit stage ,
captureCommitPhaseError
after execution
It will trigger an update similar to the following in the corresponding component ErrorBoundary
:
this.setState(
getDerivedStateFromError.bind(null, error)
)
That's why getDerivedStateFromError
asks the developer to return to a new state -- essentially, he triggers a new update.
componentDidCatch principle
Let's look at another ErrorBoundary
related lifecycle functions componentDidCatch
.
ClassComponent
this.setState
The second parameter of ---d13dce8775b35ac32accb875b1cb9656--- can receive a callback function as a parameter:
this.setState(newState, () => {
// ...回调
})
The callback fires when the triggered update is rendered to the page.
This is how componentDidCatch
is implemented.
When the error is caught, an update similar to the following will be triggered in the corresponding component ErrorBoundary
:
this.setState(this.state, componentDidCatch.bind(this, error))
Handling "uncaught" errors
It can be found that the errors in the React running process have been captured by React
itself, and then handed over to ErrorBoundary
for processing.
If ErrorBoundary
is not defined, these caught errors need to be re-throwed, giving the impression that the error was not caught .
Where is this step performed?
Similar to this.setState
, ReactDOM.render(element, container[, callback])
the third parameter can also receive a callback function .
If the developer does not define ErrorBoundary
, then React
will eventually throw an error in the callback of ReactDOM.render
.
It can be found that the implementation of ClassComponent
in ErrorBoundary
completely depends on the existing features of ClassComponent
.
And Hooks
itself does not have a callback feature similar to this.setState
, so it will be more complicated to implement.
Implement ErrorBoundary in Hooks
In addition to the obstacles mentioned above, FunctionComponent
and ClassComponent
also have differences in the details of the operating process at the source code level, and it is difficult to copy and implement.
If it must be implemented, useErrorBoundary
(the implementation of ErrorBoundary
in Hooks
) should be used under the guidelines of maximizing reuse of existing infrastructure Similar to the following:
function ErrorBoundary({children}: {children: ReactNode}) {
const [errorMsg, updateError] = useState<Error | null>(null);
useErrorBoundary((e: Error) => {
// 捕获到错误,触发更新
updateError(e);
})
return (
<div>
{errorMsg ? '报错:' + errorMsg.toString() : children}
</div>
)
}
The triggering method of ---6bc4d66a91c39dd4dc161dcc18686023 useErrorBoundary
is similar to useEffect
:
useErrorBoundary((e: Error) => {
// ...
})
// 类似
useEffect(() => {
// ...
})
ClassComponent
中ErrorBoundary
原理与useEffect
原理,实现了原生Hooks —— useErrorBoundary
。
Interested friends can experience the effect in the useErrorBoundary online example .
Summarize
ErrorBoundary
ClassComponent
使用了---e8bdfc99e978542ee1b58972a464b4dd this.setState
的回调函数特性,这使得---714bb9a59d380700dee8ee1f5a91407a Hooks
Development costs.
The author guesses that this is one of the reasons why the corresponding native Hooks
is not provided.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。