15
votes

Mettre à jour un tableau dans React à l'aide de Hooks

J'essaie de comprendre le fonctionnement de l'API React Hook. J'essaye d'ajouter un numéro à une liste. Le code que j'ai commenté, c'est-à-dire myArray.push ... ne semble pas effectuer l'opération, bien que le code ci-dessous fonctionne correctement. Pourquoi en est-il ainsi?

import React, {useState} from 'react'

export default () => {

  const [myArray, setArray] = useState([1,2,3])

  return (
    <div>
      {myArray.map((item=>{

        return <li>{item}</li>

      }))}
      <button onClick = {()=>{

        // myArray.push(myArray[myArray.length-1]+1)
        // setArray(myArray)

        setArray([...myArray, myArray[myArray.length-1]+1])

      }}>Add</button>
    </div>
  )
}


6 commentaires

Y a-t-il une raison pour laquelle vous essayez d'implémenter un composant avec état en tant que composant fonctionnel?


@SZenC pourquoi ne le feraient-ils pas, maintenant que les crochets existent?


Je crois que myArray est this.state.myArray et comme d'habitude, vous ne devriez pas muter l'état donc auparavant vous ne jamais this.state.myArray.push(....) , ce qui signifie également que vous ne devriez pas essayer de myArray.push maintenant


[...myArray, myArray[myArray.length-1]+1] !== myArray , ce qui provoquera le nouveau rendu du composant.


@Tholle Cela a du sens, donc React compare le myArray existant et ce que nous passons et s'il y a un changement de rendu? Et dans le premier cas, je passe myArray lui-même à setArray, donc il n'y a pas de rendu?


@JithinKs C'est vrai. React fera une comparaison stricte === sous le capot, et comme myArray.push ajoute simplement un autre élément au tableau existant, il ne sera pas rendu. [...myArray, myArray[myArray.length-1]+1] crée cependant un tout nouveau tableau. Si vous vous en tenez à la règle empirique de ne pas muter directement l'état, vous ne rencontrerez pas ces problèmes.


3 Réponses :


6
votes

Vous ne mutez pas le tableau dans le code de commentaire et, par conséquent, lorsque vous essayez de setState, les hooks vérifient en interne que le même état est passé car la référence ne se met pas à jour pour myArray et par conséquent, ne déclenchera pas de nouveau rendu.

Cependant, dans le code de travail, vous créez une nouvelle instance de tableau et, par conséquent, la mise à jour fonctionne correctement


0 commentaires

20
votes

Je recommanderais d'utiliser useReducer pour tout ce qui est plus compliqué qu'une seule valeur.

function App() {
  const [input, setInput] = useState(0);

  const [myArray, dispatch] = useReducer((myArray, { type, value }) => {
    switch (type) {
      case "add":
        return [...myArray, value];
      case "remove":
        return myArray.filter((_, index) => index !== value);
      default:
        return myArray;
    }
  }, [1, 2, 3]);

  return (
    <div>
      <input value={input} onInput={e => setInput(e.target.value)} />
      <button onClick={() => dispatch({ type: "add", value: input})}>
        Add
      </button>

      {myArray.map((item, index) => (
        <div>
          <h2>
            {item}
            <button onClick={() => dispatch({ type: "remove", value: index })}>
              Remove
            </button>
          </h2>
        </div>
      ))}
    </div>
  );
}


0 commentaires

0
votes

Vous pouvez utiliser un moyen de cloner en profondeur un objet et de l'utiliser comme variable temporaire pour modifier la valeur de votre tableau.

Voici un exemple avec votre code:

import React, { useState } from 'react'

export default () => {
  const [myArray, setArray] = useState([1, 2, 3])
  var tmpArray = JSON.parse(JSON.stringify(myArray))

  return (
    <div>
      {myArray.map((item) => {
        return <li>{item}</li>
      })}
      <button
        onClick={() => {
          tmpArray.push(tmpArray[tmpArray.length - 1] + 1)
          setArray(tmpArray)
        }}
      >
        Add
      </button>
    </div>
  )
}


0 commentaires