I guarantee that 99% of people who are new to React have been puzzled by the following phenomenon.
const Counter = () => {
let counter = 0;
return <button onClick={() => counter++}>{counter}</button>;
};
Why isn't the counter going up on the screen when you press the button?
Do you know why counter doesn't go up when you press the button after you have used useState?
So, how does React work fundamentally?
/* html */
<body>
<div id="app"></div>
</body>;
/* js */
const $app = document.getElementById("app");
const jsx = <div>Hello</div>;
ReactDom.render(jsx, $app);
After receiving the JSX.Element, it is parsed into a pure HtmlElement, specified a specific HtmlElement, and renders the parsed value <div>Hello</div>
under that HtmlElement.
To help understand it, here's what it looks like in Vanilla JS:
const $app = document.getElementById("app");
const $divElement = doucment.createElement("div");
$divElement.innerText = "Hello";
$app.appendChild($divElement);
Getting back on track, what will happen if you run the following code?
const $app = document.getElementById("app");
let jsx = <div>Hello</div>;
ReactDom.render(jsx, $app);
setTimeout(() => {
jsx = <div>Nice to meet you</div>;
}, 3000); // Changes the value of jsx to <div>Nice to meet you</div> after 3 seconds
The answer is that the text displayed on the screen does not change from "Hello"
to "Nice to meet you."
The reason is the same as the counter example we started with.
Because...
It's because we didn't call ReactDom.render()
again!
const $app = document.getElementById("app");
let jsx = <div>Hello</div>;
ReactDom.render(jsx, $app);
setTimeout(() => {
jsx = <div>Nice to meet you</div>; // Changes the value of jsx to <div>Nice to meet you</div>
ReactDom.render(jsx, $app); // Applies the changed value under $app again.
}, 3000);
If you call ReactDom.render()
again in the timeout callback, the text on the screen will finally change to "Nice to meet you."
Now let's apply this to the counter example...
const Counter = () => {
let counter = 0;
return <button onClick={() => counter++}>{counter}</button>;
};
How can we apply it here?
Are you struggling with how to apply ReactDom.Render
?
We don't actually need to import the ReactDom.Render
function here.
const Counter = () => {
const [counter, setCounter] = useState(0);
return (
<button onClick={() => setCounter((prev) => prev + 1)}>{counter}</button>
);
};
const $app = document.getElementById("app");
ReactDom.render(<Clicker />, $app);
The setState
function of the array returned by useState
(in this case, setCounter) calls ReactDom.Render
internally every time it is executed.
In summary...
The reason why the counter doesn't increment when the button is clicked in the initial Counter example is simple.
It's because we haven't actually manipulated the HtmlElement.
We need to parse the JSXElement into an actual HtmlElement using ReactDom.render
and then render it on the DOM
to see the value change on the screen.
Top comments (0)