1
votes

Comment s'assurer que l'état n'est pas périmé dans React hook

Les boutons que je crée en utilisant ci-dessous semblent être en retard dans la valeur selectedButtonIdx .

Le toggleSelected n'est-il pas terminé au moment où getClass est appelé?

function ButtonGroup(props) {
    const [selectedButtonIdx,setIdx]=useState(props.loadCurrentAsIndex);

    const toggleSelected = (e) => {
        setIdx(parseInt(e.target.dataset.index));
        props.onclick(e);
    };

    const getClass = (index) => {
        return (selectedButtonIdx === index) ? classnames('current', props.btnClass)
            : classnames(props.btnClass)
    };

    let buttons = props.buttons.map((b, idx) => <Button key={idx} value={b.value} index={idx} text={b.text}
                                                        onclick={e => toggleSelected(e)}
                                                        btnClass={getClass(idx)}/>);

    return (
        <div>
            {buttons}
        </div>
    );
}

Chaque clic doit montrer à l'utilisateur sur quel bouton du groupe a été cliqué en changeant sa classe.


2 commentaires

Cela est probablement dû au fait que useState est asynchrone comme répondu ici .


Bonjour bonney, lisez ceci - stackoverflow.com/help/someone-answers , et essayez de fermer la question.


3 Réponses :


0
votes

La fonction setIdx, renvoyée par useState est asynchrone, cela signifie qu'elle ne sera peut-être pas terminée au moment où vous exécuterez votre prochaine fonction (comme vous l'avez deviné).

Jetez un œil à useEffect , il vous permet de spécifier une fonction à exécutée une fois qu'un élément dans votre état change, cette méthode garantira que vos fonctions sont appelées dans le bon ordre.


0 commentaires

1
votes

En regardant ceci,

const Button = (props) => {
  return <button text={props.text} data-index={props.index} onClick={props.onclick} className={props.btnClass}>{props.value}</button>
}

Button est votre composant personnalisé,

Deux choses à noter ici,

  • Vous avez fourni des accessoires onclick ( c est petit), dans votre composant réel, il devrait être onClick = {props.onclick}
  • Vous avez utilisé e.target.dataset.index , pour travailler avec dataset nous devrions avoir un attribut avec le préfixe data- . Ainsi, votre index doit être data-index dans votre composant réel.
  • Donc, enfin, votre composant Button devrait être,

    <Button 
      key={idx} 
      value={b.value} 
      index={idx} 
      text={b.text}
      onclick={e => toggleSelected(e)}
      btnClass={getClass(idx)}
    />
    

    Démo


    0 commentaires

    0
    votes

    Pour le moment, je ne vois rien de mal ici.

    Comment ça marche:

    1. le rendu initial se produit, l'écouteur d'événement onClick est lié
    2. l'utilisateur clique sur un bouton, le gestionnaire d'événements appelle setIdx déclenchant un nouveau rendu
    3. un nouveau rendu est lancé, un tout nouveau selectedButtonIdx est utilisé pour le rendu (et pour l'appel getClass également)

    Vous voyez, il n'y a aucune raison de s'inquiéter si setIdx est une fonction de synchronisation ou asynchrone.


    0 commentaires