Please consider the following code: https://codepen.io/kyxey/pen/XWEWBRY
const { useRef, useState } = React;
function App() {
const inputRef = useRef(null);
const [jobs, setJobs] = useState([]);
const addJob = () => {
const newJob = inputRef.current.value;
if (newJob) {
setJobs((prevJobs) => [...prevJobs, newJob]);
}
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={addJob}>Add</button>
<ul>
{jobs.map((job) => {
const listItem = job + " " + Math.random();
return <li key={listItem}>{listItem}</li>;
})}
</ul>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
In this example, Whenever a new item gets added to the list, the entire list re-renders. You can tell this by looking at the random number in front of each item which will change with every newly items that are added to the list.
Now I know there are some duplications of this very question which I read them all. But none of them could solve my issue completely.
My question is: How can I prevent the re-render of the entire list each time a new item is added to it, WITHOUT using memo and useMemo in any shapes and forms? Meaning that whenever a new item is added to the list, only the new item is rendered and the other items on the list remain completely untouched. Again, I'm not able to use memo or useMemo to solve this.
For example:
Current behavior is like this:
- I type
Testin the input - Click the
Addbutton - A new item gets added to the list below with a random number in front of it:
• Test 0.8025874545033296 - I type
AnotherTestin the input - Click the
Addbutton - A new item gets added to the list below with a random number in front of it, BUT the random number in the front of the first item is also modified:
• Test 0.4454662757698613 • AnotherTest 0.16319305763152014
Expected behavior should be like this:
- I type
Testin the input - Click the
Addbutton - A new item gets added to the list below with a random number in front of it:
• Test 0.8025874545033296 - I type
AnotherTestin the input - Click the
Addbutton - A new item gets added to the list below with a random number in front of it, AND the random number in the front of the first item is NOT modified. Meaning that it's NOT re-rendered:
• Test 0.8025874545033296 • AnotherTest 0.16319305763152014
UPDATE:
This question was asked from me in a coding interview. They explicitly mentioned that I'm not allowed to use memo or useMemo in the sense that these are considered cheating! Now I don't know exactly why they think in such way but I'm sure there's an specific answer in their mind that is not how React is supposed to behave.
You've said:
A reasonable answer to that — quite possibly the one they were expecting — is something along the lines of: "You can do that, but it would just be reinventing
memofor no good reason, and by doing something so non-standard and unusual, it would make the code hard to understand and maintain for the next person." If they actually wanted to see a solution without using those things, I would suggest you cross them off the list of places you might consider working if you have any choice (I respect the fact you may not have a choice; I remember that vividly early in my career). That's a terrible interview question if they really wanted anything other than pushback (arguably even if they were looking for pushback), which can be indicative of a bad place to work.But again, technically, you can it with a ref by storing the rendered
lielements in it (perhaps in aMap). To me, that's much more "cheating" than doing it withmemoas you should, but... Here's an example:But even if I went so far as to show them that, I'd also show them a solution using
memoand putting the random value in the state of the job, talking about the strengths of doing it that way (not least that it's the normal, expected way to do this):