In the DisplayName component, the state keeps updating even though there is no change in state. console.log("Rendered") and console.log(value) keeps printing. I can’t understand, can someone help me on this. Below is the Code
import React, { useRef, useState, useEffect, useMemo } from "react";
import './App.css';
import FComponent from "./FComponent";
function App() {
const [name, setName] = useState("am");
const [counter, setCounter] = useState(1);
const result = useMemo(() => {
return factorial(counter)
}, [counter])
console.log("result")
const displayName = () => {
return {name};
}
return (
<div className="App">
<h1>Factorial of {counter} is: {result}
</h1>
<div>
<button onClick={() => setCounter(counter - 1)}>Decrement</button>
<button onClick={() => setCounter(counter + 1)}>Increment</button>
</div>
<hr></hr>
<div>
<div>
<label>Enter Name</label>
</div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
>
</input>
<hr></hr>
<DisplayName displayName={displayName} />
</div>
</div>
);
}
const DisplayName = ({ displayName }) => {
console.log("Rendered")
const [value, setValue] = useState("");
console.log(value);
useEffect(() => {
setValue(displayName());
})
return (<p>{`My name is ${value}`}</p>)
}
function factorial(n) {
if (n < 0) {
return -1
}
if (n === 0) {
return 1
}
return n * factorial(n - 1)
}
function ten() {
return new Date().toString()
}
export default App;
I expected that in DisplayName component, the state named value should only update once via the useEffect from "" to {"am"}. Now once it’s updated to {"am"} it should stop updating
2
Answers
Every time
App
renders, this is a new function instance:So the props change here:
Which causes that component to re-render with the new props.
You can use
useCallback
to retain the same function reference unless a dependency changes:So the function would only change if the
name
dependency changes.Since you have not specified any dependency in the useEffect hook, your component gets rendered infinitely.
To fix the issue, add displayName in the dependency array of useEffect. This will ensure that every time displayName changes the useEffect callback will be called.
eg.
If you want the displayName to be called only once on component mount add a blank array in the useEffect dependency.