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> ) }
3 Réponses :
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
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> ); }
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> ) }
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
estthis.state.myArray
et comme d'habitude, vous ne devriez pas muter l'état donc auparavant vous ne jamaisthis.state.myArray.push(....)
, ce qui signifie également que vous ne devriez pas essayer demyArray.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 commemyArray.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.