React Error Boundaries and Javascript Scope

React 16 introduced the concept of an error boundary.Official docs about error boundaries

Any React component becomes an error boundary by defining a componentDidCatch(error, info) method. componentDidCatch() will be called if any of the component’s children throw an error. It is the declarative equivalent of a try catch in imperative code. I’m a big fan, it enables very neat error handling in React.

Recently I wrote an error boundary component which makes it possible for the user to re-attempt a failed operation. While writing a test for this retry behaviour I ran into an interesting (to me) scope problem.

下面是一个减少版本的测试。

这个错误boundary component contains an error generator component. The error generator has a shouldError prop. If that is true then it throws an exception. To test the human initiated retry we need an error to occur, retry is activated then the error doesn’t reoccur.

let shouldError = true const TestComponent: React.SFC = () => (  { shouldError = false return (
error has occurred
) }} log={log} > no error
) const wrapper = mount() // error expect(wrapper.text()).toContain('error has occurred') // human initiated retry redacted for simplicity // success expect(wrapper.text()).toContain('no error')

Here’s the problem. The value of the the shouldError prop never changes so ErrorGenerator always generates an error. The variable being passed in to the prop changes but the prop assignment is never re-evaluated.

It took a lot of staring at it to realize that this

needs to be changed to this as the assignment of a local variable to the prop of the test component is only evaluated once.

shouldError} />