I would like to display an error message on my parent react component if an error occurs on a child element.
In this case an error would be a catch of a apollo mutation call for example as you can see in the GrandChild component.
Of course I could create a function in the parent component which sets a state value for the error and pass the function down to every child, grandchild and so on. But as my structure is a bit complicated it would mean a lot of work. That's why I thought of using react error boundaries. But is this the correct use case?
As I'm using nextJS, every throw Error
will display an error stacktrace in development mode, so it is impossible to display the error as a message
Parent.js
export class Parent extends Component {
render () {
return (
{ /* if there is an error in any child component, it should be displayed here */
this.props.error &&
<Message>{error}</Message>
}
<Child {...props} />
)
}
}
GrandChild.js
class GrandChild extends Component {
doAnything () {
return this.props.assumeToFail({
variables: { id: '123' }
}).catch(error => {
console.error(error) // <-- this error should be given back to parent
throw new Error('fail') // <-- should I throw the error or call a custom function?
})
}
render () {
return (
<Button onClick={this.doAnything().bind(this)}>anything</Button>
)
}
}
export default graphql(exampleMutation, { name: 'assumeToFail' })(GrandChild)
To use the error boundaries in my nextJS application I just have to add
_app.js
class MyApp extends App {
componentDidCatch (error, errorInfo) {
console.log('CUSTOM ERROR HANDLING', error)
// How do I get the error down to 'Component' in render()?
super.componentDidCatch(error, errorInfo)
}
render () {
const { Component, pageProps, apolloClient } = this.props
return <Container>
<ApolloProvider client={apolloClient}>
<Component {...pageProps} />
</ApolloProvider>
</Container>
}
}
to my _app.js file. But I'm not sure if this is the way to go... and I don't know how to get the error down to the Component
.
The best way to implement this is by using react state management like redux or fluxible.
If you are using react state management, then you can call the action by dispatch the message from the child.js
and connect to redux store in the parent.js
to get the error message easily.
If you decide to use function like what you have described, you can pass a function to the children and let the children call that function.
Parent.js
export class Parent extends Component {
state = {
error: null,
}
render () {
return (
{ /* if there is an error in any child component, it should be displayed here */
this.state.error &&
<Message>{this.state.error}</Message>
}
<Child
{...props}
defineError={(errMsg) => setState({ error: errMsg })}
/>
)
}
}
GrandChild.js
import PropTypes from 'prop-types';
class GrandChild extends Component {
static propTypes = {
defineError: PropTypes.func,
}
doAnything () {
return this.props.assumeToFail({
variables: { id: '123' }
}).catch(error => {
this.props.defineError(error);
console.error(error) // <-- this error should be given back to parent
throw new Error('fail') // <-- should I throw the error or call a custom function?
})
}
render () {
return (
<Button onClick={this.doAnything().bind(this)}>anything</Button>
)
}
}
export default graphql(exampleMutation, { name: 'assumeToFail' })(GrandChild)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With