I came accross a weird behavior.
See this fiddle. When using React 16 error handling mechanisme, namely Error Boundary, I noticed the error
parameter was empty. Upon further investigation I realised it was only the case when throwing an Error object like so :
throw new Error('The world is very strange')
However, when throwing the error this way :
throw 'The world is very strange'
The error will be available in componentDidCatch
.
Please, someone, enlighten me.
I wish to continue using new Error
because it is recommended to use it and it should give access to file and line number of throw.
Let's take a look at the code.
class Boundary extends React.Component {
constructor() {
super();
this.state = {}
}
componentDidCatch(error, info) {
this.setState({
error,
info,
})
}
render() {
if (this.state.error) {
return (
<div>
{JSON.stringify(this.state)}
</div>)
}
return this.props.children;
}
}
class Component extends React.Component {
render() {
// Why and what should i do ?
throw 'This will be available in the error parameter'
throw new Error('This one will not')
}
}
class TodoApp extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<Boundary>
<div>
<Component />
</div>
</Boundary>
)
}
}
Throwing strings is discouraged because an error is conventionally an object, preferably an instance of Error
.
There is no problem with throwing Error
. There is a problem with how it's processed:
if (this.state.error) {
return (
<div>
{JSON.stringify(this.state)}
</div>)
}
Since error.message
is non-enumerable, error
is stringified to {}
. This is expected behaviour. JSON.stringify
shouldn't be relied on as all-round representation of objects - this is what dev tools console is for.
Current representation could be fixed by extending Error
:
class HumanReadableError extends Error {
toJSON() {
return `Error: ${this.message}`;
}
}
and
throw new HumanReadableError('This will not be available');