1
votes

Problèmes avec la définition d'objet d'état successif dans les hooks reactjs

Je commence à utiliser des hooks de réaction et je décide de mettre un objet au lieu d'une variable dans la fonction useState :

const onChange = (e) => { 

    const { value } = e.target;

    setFoo({ ...foo, term: value });

    if(value) setFoo({ ...foo, loading: true });

    ...

}

...

return (
   ...
   <input onChange={onChange} value={term} />
   ...
) 

mais plus tard quand je veux le mettre à jour

const [foo, setFoo] = useState({
    term: '',
    loading: false,
    ...
});

1. Pourquoi dans le deuxième setFoo quand je vérifie le toto object J'obtiens toujours la propriété term égale à '' exactement comme la valeur initiale et l'entrée n'est pas mise à jour avec les caractères tapés?

- Lorsque je supprime le deuxième setFoo , cela fonctionne donc je suppose que setFoo est asynchrone mais comment résoudre ce problème ?.

- Je sais que nous pouvons contourner ce problème en réussissant à appeler setFoo une seule fois mais je veux connaître d'autres solutions?

2. Pourquoi ce genre de problèmes ne s'est jamais produit dans redux?


0 commentaires

3 Réponses :


1
votes

Vous pouvez résoudre le problème en appelant setFoo une seule fois avec toutes les nouvelles paires clé-valeur, comme ceci:

const onChange = (e) => { 

    const { value } = e.target;
    const loading = value ? true : false;
    setFoo({ ...state, term: value, loading });
    ....
}

Mise à jour: strong>

Pour une mise à jour d'état complexe et plus de contrôle sur cette partie, vous pouvez utiliser useReducer , et écrivez un réducteur séparé pour mettre à jour l'état.


2 commentaires

Je le sais et je viens de simplifier mon code, le point est de savoir comment utiliser la configuration d'objet d'état successif dans les hooks de reactjs?


Je pense que useReducer est ce que vous recherchez, écrivez un réducteur / une fonction séparé pour la mise à jour de l'état.



2
votes

La solution: utilisez un setFoo comme ceci:

const onChange = (e) => { 

    const { value } = e.target;

    setFoo({ term: value, loading: !!value });

    ...

}

!! signifie "convertir en valeur booléenne". p >


3 commentaires

Je le sais et je viens de simplifier mon code, le point est de savoir comment utiliser la configuration d'objet d'état successif dans les hooks de reactjs?


Je ne connais pas un moyen de faire cela avec des hooks - vous devez le faire en un seul appel setFoo .


Merci quand même @LorenzHenk;)



1
votes

1. Probablement parce que vous devez détruire foo au lieu de state

const reducer = (state, action) {
    switch(action.type) {
       case 'loading':
         return { ...state, loading: true };
       case 'loaded':
       default:
         return { ...state, loading: false };
    }
}

const initialState = {
  term: '',
  loading: false,
}
const [state, dispatch] = useReducer(reducer, initialState);
dispatch({
   type: e.target.value ? 'loaded' : 'loading'
});

exemple fonctionnel useState

2. strong > Jetez un œil aux crochets supplémentaires, en particulier useReducer

useReducer est généralement préférable à useState lorsque vous avez une logique d'état complexe qui implique plusieurs sous-valeurs ou lorsque l'état suivant dépend du précédent.

Et votre code peut devenir:

setFoo({ ...foo, term: value });

exemple de travail useReducer sur CodeSandbox


3 commentaires

1. Non @Teneff c'était juste une petite faute de frappe, 2. mais merci pour le conseil useReducer , je vais jeter un œil.


merci beaucoup @Teneff;) éditez simplement votre question pour la première partie car ce n'était qu'une faute de frappe.


Regardez @Teneff à ma question éditée, il n'y a pas besoin de la première partie de votre réponse