I'm learning reactJS and I started to learn about the state. I did this :
const famille = {
membre1: {
nom: "Steve",
age: 45
},
membre2: {
nom: "Bill",
age: 60
},
membre3: {
nom: "Mark",
age: 40
}
}
function App(props) {
const [membres, setMembres] = useState(famille);
function handleAgeChange(){
let newFamille = famille;
newFamille.membre1.age = 1;
newFamille.membre2.age = 1;
newFamille.membre3.age = 1;
setMembres(newFamille);
console.log(membres)
}
return (
<Fragment>
<div className="App">
<h1>{props.titre}</h1>
<ul>
<Membre name={membres.membre1.nom} age={membres.membre1.age}/>
<Membre name={membres.membre2.nom} age={membres.membre2.age}/>
<Membre name={membres.membre3.nom} age={membres.membre3.age}/>
</ul>
<button onClick={handleAgeChange}>Veillir</button>
</div>
</Fragment>
);
}
The <Member />
component only show {name} : {age}
My goal is to add 1 to everyone age when I click on the button. My state is correctly updating but the app isn't and I don't understand why.
CodePudding user response:
let newFamille = famille
makes newFamille
point to the reference of the old state - it doesn't make a new array/reference which is how React determines whether the state has been updated to manage the next render.
I would suggest moving from an object to an array of objects (with ids) as arrays are a little easier to manipulate. Instead of referencing a component for each family member you can map
over the array, and return a completed component on each iteration.
Likewise, in the handler, you can map
over the array to produce a new array of objects which you can use to set the state.
const { Fragment, useState } = React;
function Example({ titre, famille }) {
const [membres, setMembres] = useState(famille);
// `map` over the membres array to create a new
// array of updated membres
function handleAgeChange() {
const updated = membres.map(membre => {
membre.age;
return membre;
});
// And use that to set the new state
setMembres(updated);
}
// Make sure you use the id to set the key
return (
<Fragment>
<div className="App">
<h1>{titre}</h1>
<ul>
{membres.map(membre => {
return (
<Membre
key={membre.id}
nom={membre.nom}
age={membre.age}
/>
);
})}
</ul>
<button
onClick={handleAgeChange}
>Veillir
</button>
</div>
</Fragment>
);
}
function Membre({ nom, age }) {
return <li>{nom} - {age}</li>;
}
const famille = [
{id: 1, nom: 'Steve', age:45},
{id: 2, nom: 'Bill', age:60},
{id: 3, nom: 'Mark', age:40}
];
ReactDOM.render(
<Example titre="Famille" famille={famille} />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
CodePudding user response:
Just try this.
function handleAgeChange(){
setMembres({
membre1: {
...membres.membre1,
age: membres.membre1.age 1,
},
membre2: {
...membres.membre2,
age: membres.membre2.age 1,
},
membre3: {
...membres.membre3,
age: membres.membre3.age 1,
}
});
console.log(membres)
}
To update an object state, you need create a new object to do this.
CodePudding user response:
Thank you all for your help ! Your both solutions are working and I founded a third one that much easier to understand for me.
const famille = {...membres};
famille.membre1.age = 1;
famille.membre2.age = 1;
famille.membre3.age = 1;
setMembres(famille);