So I am Trying to implement Google Forms Clone and I want to add new question div at a specific index. But my div array's state gets lost.
//array of Divs
const [questionDivs, setQuestionDivs] = useState([]);
//Function to add new div to the questionDivs at a specific index
const addQuestionDiv = () => {
const newKey = `question_${questionDivs.length + 1}`;
const newQuestionDivs = [...questionDivs];
newQuestionDivs.splice(selectedDivIndex + 1, 0, (
<div
key={newKey}
className="my-[1%] ml-[28%] w-[44%] min-h-[30%]"
onClick={handleQuestionClick}
>
{<Questions key={newKey}/>}
</div>
));
setQuestionDivs(newQuestionDivs);
};
//Rendering the divs
{questionDivs.map((questionDiv, index) => (
<div key={`question_${index}`} onClick={()=> SetCurrentDivHandler(index)}>{questionDiv}</div>
))}
[Here are 2 question divs and when i press the + icon which i Highlighted in the image, I want a new div to be added right below the current selected div, I have already implemented a function where you get the index of the current div. ] (https://i.stack.imgur.com/jskYD.png) [When I press the + button a new div is getting added but the div which is below it is loosing its state, It had Option A and Option B but now it is empty after Insertion of new Div. But the div above that didn't loose its state. To whichever index I try to add a new div, the indexes which comes after that looses their states. I even tried looping but same results] (https://i.stack.imgur.com/a8OAT.png)
Problem
React uses
keys as part of the decision to update the DOM. A comparison is made between the old DOM tree and the new DOM tree. For elements with the same key, React will decide it can keep the DOM trees the same.As you map over
questionDivsyou return adivwith its key essentially set to its index position in the array (we can ignore thequestion_prefix because that is constant). When you insert something, all subsequent items will have their keys changed, resulting in React rebuilding those trees and losing state. Here's a demo of the problem, note thedivusing the index key wrapping theQuestioncomponent – this demo is also reused in the solution so a comparison can be easily made.Solution
You need more stable keys. IDs of some sort are a good choice. Not critical to the solution but generally important: you should also consider thinking about views as a representation of data – this means instead of storing parts of the view as JSX inside an array, just storing the data that represents it and mapping it across to the JSX representation. Below is a demo, note the following:
Questionscomponent).The demo is also naive in the sense that the state is an array of IDs. A more complex application might store a list/map of objects representing the state of each question instead which would be kept in sync with a server. However, given the complexity, I won't show that in the demo.