In the reactjs UseEffect documentation, we find below code where the document.title is updated using the useEffect hook
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count 1)}>
Click me
</button>
</div>
);
}
export default App;
I am trying to understand the difference between using the useEffect hook without passing the second argument ( like [] for mount only) and just using the code to update the title (or any other code) outside without using the hook.
import { useState, useEffect } from 'react';
function App() {
const [count, setCount] = useState(0);
document.title = `You clicked ${count} times`;
// useEffect(() => {
// document.title = `You clicked ${count} times`;
// });
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count 1)}>
Click me
</button>
</div>
);
}
export default App;
What is the difference?
CodePudding user response:
The answer clearly lies in another question. The question is when does useEffect run in a react application?
React official docs/team says that useEffect
is a way to lets us perform our sideffects
after the first render and every other subsequent render.
So, in your second example, the real dom is manipulated at first render too. This will throw an error in case the dom node is not painted to the screen. Luckily, your second example will not throw an error because the document.title
will be going to be loaded (default behavior of webpage).
That's why all folks recommend us to do dom-manipulation
inside the useEffect.
CodePudding user response:
The main difference is The function passed to useEffect will run after the render is committed to the screen
import { useState, useEffect } from 'react';
function Bla() {
const [count, setCount] = useState(0);
console.log(`You clicked ${count} times before render `) // before the render phase
useEffect(() => {
console.log(`You clicked ${count} times after render `) //after render phase
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count 1)}>
Click me
</button>
</div>
);
}
export default Bla;
CodePudding user response:
The first line from the docs says :
The Effect Hook lets you perform side effects in function components.
A simple definition of side effect is an action that performs something that might not be predictable. Setting storage, changing DOM etc.
Your action of changing the title
is a side effect. A good SO link
Any code outside event handlers and hooks definition will run on every render. So, if you write your title
changing statement it will run on every render. Now, you do not want to update the title
in every render.
You want it to execute after the DOM has been painted and render cycle is complete. For which you have useEffect. With useEffect you have control on that. The below code will run after every render.
useEffect(() => {
document.title = `You clicked ${count} times`;
});
Ideal because the UI is not affected by this action, and there is no need for it to be included in the code that is determining the output
(UI) you have to show.