IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

React Discussion :

Hook useEffect dépendance crée une boucle infini


Sujet :

React

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau candidat au Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Octobre 2022
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Octobre 2022
    Messages : 1
    Par défaut Hook useEffect dépendance crée une boucle infini
    Bonjour,
    Je suis nouveau en JS particulièrement avec React, je me suis lancé à comprendre l'utilisation des hooks et particulièrement "useEffect".

    Mais j'ai un petit soucis, voici la situation, j'ai un useState qui représente une liste d'objet. Ces objet ont deux string, l'un contient un charactère/une lettre, l'autre contient une couleur (qui est le nom d'une classe CSS que je défini à l'intérieur de mon composant avec className={}). Et j'ai un input où les données écritent sont lu par un autre useState.

    Bon ma problématique est la suivante, j'ai donc une liste/suite de charactères(ex "ABCDEF"), où ces lettres ont une couleur initiale(ex noir), lorsque j'écris dans mon input je veux, si la lettre de mon input est identique à la lettre de ma liste, sa couleur passe en vert, si elle est fausse en rouge, et les suivantes ect...
    Sauf que j'ai compris qu'avec react quand on change une valeur d'un useState, il y avait un décalage de 1, exemple quand j'écris dans mon input ex:"A" la valeur de mon input est égale à rien, quand j'écris la lettre suvante ex:"AB" la valeur de mon input deviens "A", "ABC" égale "AB" ect...
    Pour contourner ce principe j'ai trouvé le hook "useState" qui lui renvoi la valeur "en direct" de mon useState. Voici mon code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
        const [inputValue, setInputValue] = useState('');
        const [words, setWords] = useState([{str: 'A', color: 'color-one'}, {str: "B", color:"color-one"}, {str: "C", color: "color-one"}]);
     
        const inputHandler =(event) =>{
            const string = event.target.value;
            setInputValue(string);
        }
     
        useEffect(()=>{
            const charWords = words.map(word => word.str);
            const charInput = inputValue.charAt(inputValue.length-1);
            if(charInput === charWords[inputValue.length-1]){
                const goodAnswer = words.map((elem,i)=>{
                    if(i === inputValue.length-1){
                        return {...elem, color: "color-two",}
                    }else{
                        return elem;
                    }
                })
                setWords(goodAnswer);
            }else{
                if(charInput ===""){
     
                }else{
                    const wrongAnswer = words.map((elem,i)=>{
                    if(i === inputValue.length-1){
                        return {...elem, color: "wrong-answer",}
                    }else{
                        return elem;
                    }
                })
                setWords(wrongAnswer);
                }
            }
        }, [inputValue]);
     
        return(
            <div>
                {words.map((elem)=>(
                    <label className={elem.color}>{elem.str}</label>
                ))}   
                <input value={inputValue} onChange={inputHandler}/>
            </div>
        )
    Alors la bonne nouvelle c'est que tout fonctionne quand j'écris dans mon input ca compare par rapport à la liste de lettre et ca change la couleur en fonction. Bon alors où est le probléme si tout fonctionne me diriez vous? Et bien ca se passe dans la console(non celle du navigateur mais celle de nodejs quand je fais "npm start"). J'ai une erreur (ou plutot un "avertissement") me disant ceci:
    "Line 39:8: React Hook useEffect has a missing dependency: 'words'. Either include it or remove the dependency array react-hooks/exhaustive-deps"
    Alors si j'ai bien compris il me demande soit d'ajouter la variable manquante (ici "words") dans le tableau de dépendance, soit de supprimer le tableau. Si je supprime le tableau rien ne fonctionne, et si j'ajoute "words" au tableau je n'ai plus d'erreur dans la console en revanche sur mon navigateur ca crée une boucle infini et il n'est pas content du tout.

    Donc ma question est, comment résoudre ce problème ? Ou bien est-ce vraiment un problème, vu que le code fonctionne, du coup est-ce si grave de laisser mon code ainsi ?
    Ou alors je m'y prend vraiment comme un manche et qu'il faudrait que j'utilise une méthode complétement différente et plus sure, que mon petit cerveau n'a pas su trouver.

    Merci de vos futurs réponses.

  2. #2
    Membre Expert
    Avatar de gwyohm
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2007
    Messages
    925
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 925
    Par défaut
    hello, je pense que words devrait être une dépendance, mais dans useEffect, je pense que
    n'est jamais vrai. Essaye au début du useEffect de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(inputValue.lenth === 0) {return;}

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2019
    Messages : 6
    Par défaut
    Bonjour ! Je suis également encore débutant en React, mais je vais tenter de t'aider

    Déjà, la boucle infinie est logique : si tu ajoutes words dans un useEffect qui ... met à jour words, avec setWords, tu tournes en rond
    (après, je ne sais pas ce que signifie exactement le message d'erreur que tu as).


    Par contre, si j'ai bien compris ce que tu veux faire, j'ai l'impression que tu te compliques.

    Si je résume, tu as un mot de départ (une succession de lettres), qui est connue par avance (c'est une constante tableau, voir directement une string pour faire plus simple : elle peut même être passé dans les props de ton composant).

    Et lorsque l'utilisateur saisit un mot, tu veux directement afficher ce qu'il tape coloré, de la bonne manière suivant que les lettres sont correctes ou non (par contre, je n'ai pas compris si c'était toujours le même jeu de couleur pour chaque lettre - par exemple vert/rouge - ou si cela dépend pour chaque lettre. Ca ne change cependant pas la logique, donc je prend le cas le plus simple).

    Bref, si l'on résume, la seule chose qui varie et qui implique de rerender ton composant, c'est le mot tapé par l'utilisateur.
    A partir de ce mot, en comparant avec ta constante de départ, tu peux recréer l'affichage, en parcourant chaque lettre de la saisie de l'utilisateur et la comparant.

    On va se baser uniquement et stocker en state la partie variable : la saisie de l'utilisateur.



    Par ailleurs, autre conseil - même si là ça n'a pas d'incidence car on rerender le composant à chaque fois de toutes façons - il est plus simple et propre d'utiliser un useRef pour accéder directement aux infos d'un input (et d'ailleurs, cela te permet de récupérer ce que l'utilisateur tape, sans forcément faire un rerender du composant, c'est donc une bonne habitude ... d'ailleurs je pense qu'il y aurait sans doute une solution à ton problème sans même passer par un useState, en manipulant directement le DOM, via éventuellement un autre useRef, et donc sans recharger du tout le composant ... mais bon, je ne sais pas si c'est une bonne méthode).


    Donc du coup, ça donnerait quelquechose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    import React, { useRef, useState } from 'react'
     
     
    const InputValidation = ({correctWord}) => {
     
      const myInput = useRef("");
      const [saisie, setSaisie] = useState('');
     
       const handleChange = () => {
            setSaisie(myInput.current.value);
       }
      return (
        <div>
            <input ref={myInput} type="text" onChange={handleChange}/>
            <div>
                { saisie.split('').map( (letter, index) => 
                    ( index<correctWord.length && letter === correctWord[index] ) 
                        ? <span key={`l${index}`} style={{color:"green"}}>{letter}</span>
                        : <span key={`l${index}`} style={{color:"red"}}>{letter}</span>
                )}
            </div>
        </div>
      )
    }
     
    export default InputValidation

    Si tu veux que le mot soit apparent directement en noir au départ (et que les lettres se colorent au fur et à mesure), il faut inverser la logique du map : parcourir la chaîne de départ et comparer avec le caractère au même index dans la saisie.


    Mais bon, donc, à mon avis l'idée est là : ne pas chercher à stocker le rendu (les styles) de chaque lettre dans un état, mais tout calculer lors du rendu à partir de ce que tu as dans l'état.

Discussions similaires

  1. Réponses: 18
    Dernier message: 26/04/2006, 11h39
  2. Une boucle infinie crontab
    Par tsing dans le forum Administration système
    Réponses: 10
    Dernier message: 10/04/2006, 10h28
  3. Select qui fais une boucle infinie
    Par MaitrePylos dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 28/03/2006, 17h29
  4. Réponses: 10
    Dernier message: 24/12/2005, 15h35
  5. [FTP] comment corriger une boucle infinie ?
    Par sofybj dans le forum Langage
    Réponses: 8
    Dernier message: 08/11/2005, 14h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo