Home > Software design >  App state updated but dont update the app
App state updated but dont update the app

Time:11-09

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);
  • Related