'Why did React "restart" the render-phase?
Sandbox link : Link to This CodeSandbox.io
Please help me understand the sequence of execution in this code.
When an error is thrown in child component ( Display ), the getDerivedStateFromError() runs and sets hasError state to true. After that, as expected render() runs....
What I didn't understand is.... Why is the constructor being called again ? This is counter-intuitive... Please explain the reason for its calling...
What did React achieve by restarting everything from the constructor ? It should've simply displayed the fallback UI..But it ran the constructor again and only after facing the same error again did it show the fallback UI. Why did this happen ?
This is my App.js file
import React from "react";
export const Button = (props) => {
return (
<button className={props.className} onClick={props.onClick}>
{props.children}
</button>
);
};
function Display(props) {
throw new Error();
return <h1>Counter {props.i}</h1>;
}
class Counter extends React.Component {
constructor() {
super();
console.log("constr ran");
this.state = {
count: 0,
updated: false,
firstRender: false,
hasError: false,
};
this.incHandler = this.incHandler.bind(this);
}
static getDerivedStateFromError() {
console.log("getDerivedStateFromError Ran...");
return {
hasError: true,
};
}
incHandler() {
this.setState((prevState) => {
return {
count: prevState.count + 1,
updated: true,
};
});
console.log(this.state.count);
}
decHandler = () => {
this.setState((prevState) => {
return {
count: prevState.count - 1,
updated: true,
};
});
console.log(this.state.count);
};
render() {
console.log("render() ran... hasError: ", this.state.hasError);
if (this.state.hasError) {
return (
<div className="App">
<h1>Error happened!</h1>;
</div>
);
}
return (
<div className="App">
<Display i={this.state.count} />
<Button className="button" onClick={this.incHandler}>
Increment
</Button>
<Button className="button" onClick={this.decHandler}>
Decrement
</Button>
<Button
className="button"
onClick={() => {
throw new Error();
}}
>
This Will Throw Error
</Button>
</div>
);
}
}
export default Counter;
This is my index.js file
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
reportWebVitals();
Just wanted to add more to this....
Even when componentDidCatch() is used to catch errors in child components,
Behaviour of React is same...
Please see below image and code

In App.js I made this small modification. This is also causing re-running of constructor.... Why ?
// static getDerivedStateFromError() {
// console.log("getDerivedStateFromError Ran...");
// return {
// hasError: true,
// };
// }
componentDidCatch() {
console.log("componentDidCatch running");
this.setState({ hasError: true });
}
So, apparently, whenever React encounters an error it tries to start everything from constructor...(with the hope of eliminating it...) It sure looks like that....
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

