I am unsure what I am doing wrong..If I switch the state to a counter it works, but I need it to be an array of objects to store different values for each div. Not sure why the dom never updates.
import "./styles.css";
import { useState } from "react";
// The parent component
const App = () => {
const [textBoxDivs, setTextBoxDivs] = useState([]);
const addNewTextBox = () => {
const textboxes = textBoxDivs;
const numOfTextBoxDivs = textBoxDivs.length;
const newTextBox = { id: `div${numOfTextBoxDivs + 1}` };
textboxes.push(newTextBox);
setTextBoxDivs(textboxes);
console.log(textboxes, "boxes");
};
return (
<div>
<button onClick={() => addNewTextBox()}>Click me</button>
{textBoxDivs.length > 0
? textBoxDivs.map((item, index) => (
<div key={index} id={item.id}>
text
</div>
))
: null}
</div>
);
};
export default App;
codeSandbox: https://codesandbox.io/s/friendly-water-wf4f5?file=/src/App.js:0-749
Because you are attempting to mutate existing state by pushing a new item to textBoxDivs, rather than providing a new state, breaking one of the fundamental rules of React.
Instead of pushing to your textBoxDivs array, provide a new copy of your state, with the new item inserted:
import "./styles.css";
import { useState } from "react";
// The parent component
const App = () => {
const [textBoxDivs, setTextBoxDivs] = useState([]);
const addNewTextBox = () => {
const numOfTextBoxDivs = textBoxDivs.length;
const newTextBox = { id: `div${numOfTextBoxDivs + 1}` };
setTextBoxDivs((textBoxDivs) => ([
...textBoxDivs,
newTextBox
]));
};
return (
<div>
<button onClick={() => addNewTextBox()}>Click me</button>
{textBoxDivs.length}
{textBoxDivs.length > 0
? textBoxDivs.map((item, index) => (
<div key={index} id={item.id}>
text
</div>
))
: null}
</div>
);
};
export default App;
Reading:
I should note that there's nothing inherently wrong with using push in this scenario, the issue is that you are pushing to existing state. You could just as easily do
// Still creating a new state from the current state
const newTxtBoxDivs = [...textBoxDivs];
newTxtBoxDivs.push(newTextBox);
setTextBoxDivs(newTxtBoxDivs);
For the same effect. The key take-away is that newTxtBoxDivs does not refer to the same object as textBoxDivs, it refers to a copy of it.