123 votes

Comment mettre à jour les états lors d'un changement dans un tableau d'objets dans React Hooks

J'ai récupéré des données stockées à l'aide de useState dans un tableau d'objets, les données ont ensuite été sorties dans des champs de formulaire. Et maintenant, je veux pouvoir mettre à jour les champs (état) au fur et à mesure que je tape.

J'ai des exemples de personnes mettant à jour l'état de la propriété dans un tableau, mais jamais pour l'état d'un tableau d'objets, donc je ne sais pas comment le faire. J'ai l'index de l'objet passé à la fonction de rappel mais je ne savais pas comment mettre à jour l'état en l'utilisant.

 
// sample datas structure
const datas = [
    {
      id:   1,
      name: 'john',
      gender: 'm'
    }
    {
      id:   2,
      name: 'mary',
      gender: 'f'
    }
]

const [datas, setDatas] = useState([]);

const updateFieldChanged = index => e => {

    console.log('index: ' + index);
    console.log('property name: '+ e.target.name);

        setData() // ??
}

return (
    <React.Fragment>
        { datas.map( (data, index) => {
              <li key={data.name}>
                <input type="text" name="name" value={data.name} onChange={updateFieldChanged(index)}  />
              </li>
          })
        }
    </React.Fragment>
)

229voto

Steffan Points 1823

Voici comment procéder :

 // sample datas structure
/* const datas = [
    {
      id:   1,
      name: 'john',
      gender: 'm'
    }
    {
      id:   2,
      name: 'mary',
      gender: 'f'
    }
] */ // make sure to set the default value in the useState call (I already fixed it)

const [datas, setDatas] = useState([
    {
      id:   1,
      name: 'john',
      gender: 'm'
    }
    {
      id:   2,
      name: 'mary',
      gender: 'f'
    }
]);

const updateFieldChanged = index => e => {

    console.log('index: ' + index);
    console.log('property name: '+ e.target.name);
    let newArr = [...datas]; // copying the old datas array
    newArr[index] = e.target.value; // replace e.target.value with whatever you want to change it to

    setDatas(newArr); // ??
}

return (
    <React.Fragment>
        { datas.map( (data, index) => {
              <li key={data.name}>
                <input type="text" name="name" value={data.name} onChange={updateFieldChanged(index)}  />
              </li>
          })
        }
    </React.Fragment>
)

117voto

spender Points 51307

Vous pouvez le faire sans mutation en mappant votre ancien tableau dans un nouveau, en échangeant ce que vous souhaitez modifier contre un élément mis à jour en cours de route.

 setDatas(
    datas.map(item => 
        item.id === index 
        ? {...item, someProp : "changed"} 
        : item 
))

15voto

ohlr Points 1511
setDatas(datas=>({
   ...datas,
   [index]: e.target.value
}))

avec index étant la position cible et e.target.value la nouvelle valeur

8voto

Heroe__ Points 93

Vous n'avez même pas besoin d'utiliser l'index (à l'exception de la clé si vous le souhaitez) ni de copier l'ancien tableau de données, et vous pouvez même le faire en ligne ou simplement passer des données en argument si vous préférez que updateFieldChanged ne soit pas en ligne. C'est très rapide comme ça :

   const initial_data = [
    {
      id: 1,
      name: "john",
      gender: "m",
    },
    {
      id: 2,
      name: "mary",
      gender: "f",
    },
  ];

  const [datas, setDatas] = useState(initial_data);

  return (
    <div>
      {datas.map((data, index) => (
        <li key={index}>
          <input
            type="text"
            value={data.name}
            onChange={(e) => {
              data.name = e.target.value;
              setDatas([...datas]);
            }}
          />
        </li>
      ))}
    </div>
  );
};

5voto

C'est ce que je fais:

 const [datas, setDatas] = useState([
  {
    id: 1,
    name: "john",
    gender: "m",
  },
  {
    id: 2,
    name: "mary",
    gender: "f",
  },
]);

const updateFieldChanged = (name, index) => (event) => {
  let newArr = datas.map((item, i) => {
    if (index == i) {
      return { ...item, [name]: event.target.value };
    } else {
      return item;
    }
  });
  setDatas(newArr);
};

return (
  <React.Fragment>
    {datas.map((data, index) => {
      <li key={data.name}>
        <input
          type="text"
          name="name"
          value={data.name}
          onChange={updateFieldChanged("name", index)}
        />
      </li>;
      <li key={data.gender}>
        <input
          type="text"
          name="gender"
          value={data.gender}
          onChange={updateFieldChanged("gender", index)}
        />
      </li>;
    })}
  </React.Fragment>
);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X