3 votes

La liaison bidirectionnelle ne fonctionne pas avec plusieurs cases à cocher chargées dynamiquement dans React

J'ai un problème dans la gestion des cases à cocher chargées dynamiquement à partir d'un jeu de données en React. (J'utilise React avec uniquement des composants fonctionnels et des hooks avec la bibliothèque reactstrap) Voici le jeu de données :

[
    {
       "expertiseAreaId": 1,
       "descriptionEng": "Analysis and Mapping",
       "descriptionFra": "Analyse et cartographie",
       "checked": false
    },
            {
       "expertiseAreaId": 1,
       "descriptionEng": "Strategic planning",
       "descriptionFra": "Planification stratégique",
       "checked": false
    },
            {
       "expertiseAreaId": 1,
       "descriptionEng": "Project/Proposal Design",
       "descriptionFra": "Projet/Proposition de projet",
       "checked": false
    },
    ....
]

Le jeu de données est contenu dans expertiseAreasData. J'utilise une autre variable d'état (expertiseAreaIds) pour stocker les booléens qui seront lus dans la propriété checked des cases à cocher (type Input="checkbox")

    const [expertiseAreaIds, setExpertiseAreaIds] = useState([false, false, false, false, false, false, false, false, false, false, false, false, false, false]);
    const [expertiseAreasData, setExpertiseAreasData] = useState([]);

Voici le JSX :

                    Domaine d'expertise *

                        {expertiseAreasData.length > 0 ? expertiseAreasData.map((data, idx) => (
                             onChangeExpertiseAreas(idx)} />
                            {language.toUpperCase() === "EN" && {data.descriptionEng}}
                            {language.toUpperCase() === "FR" && {data.descriptionFra}}
                        )) : Aucune donnée chargée.
                        }

Lorsque j'appelle l'événement onChangeExpertiseAreas, je mets à jour à la fois expertiseAreaIds et expertiseAreasData

    const onChangeExpertiseAreas = (idx) => {
        var data = expertiseAreaIds;
        var value = data[idx];

        data[idx] = !value;
        setExpertiseAreaIds(data);

        var dt = expertiseAreasData;
        var element = dt[idx];
        element.checked = !value;
        dt[idx] = element;

        setExpertiseAreasData([]);
        setExpertiseAreasData(dt);
}

Lorsque je coche la case à cocher, l'état est mis à jour correctement, mais le JSX n'est pas mis à jour et j'affiche toujours les cases à cocher à false (état initial). J'espère que quelqu'un d'autre a eu le même problème

2voto

Zohaib Ijaz Points 6945

Vous modifiez des données/états ce qui provoque ce problème. Vous devez toujours attribuer une nouvelle référence à une valeur d'état afin de déclencher un nouveau rendu.

Faites ceci

const onChangeExpertiseAreas = (idx) => {
    var data = [...expertiseAreaIds]; // faire une copie du tableau, changer la référence
    var value = data[idx];

    data[idx] = !value;
    setExpertiseAreaIds(data);

0voto

Roberto Calvo Points 31

Exactement, c'était le problème ! J'ai trouvé la solution il y a peu de temps. Merci pour l'explication. Voici mon nouveau code :

Variable d'état :

const [expertiseAreasData, setExpertiseAreasData] = useState([]);

JSX :

                    Domaine d'expertise *

                        {expertiseAreasData.length > 0 ? expertiseAreasData.map((data, idx) => (
                             onChangeExpertiseAreas(idx)} />
                            {language.toUpperCase() === "EN" && {data.descriptionEng}}
                            {language.toUpperCase() === "FR" && {data.descriptionFra}}
                        )) : Aucune donnée chargée.
                        }

Evénement onChange :

const onChangeExpertiseAreas = (idx) => {
    var value = expertiseAreasData[idx].checked;
    expertiseAreasData[idx].checked = !value;
    setExpertiseAreasData([...expertiseAreasData]);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X