web-dev-qa-db-fra.com

React hooks: comment mettre à jour l'état d'un objet imbriqué avec useState ()?

J'ai un composant qui reçoit un accessoire qui ressemble à ceci:

const styles = {
    font: {
        size: {
            value: '22',
            unit: 'px'
        },
        weight: 'bold',
        color: '#663300',
        family: 'arial',
        align: 'center'
    }
};

J'essaie de mettre à jour la propriété align, mais lorsque j'essaie de mettre à jour l'objet, je finis par remplacer l'objet entier par juste la propriété align.

voici comment je le mets à jour:

const { ...styling } = styles;
const [style, setStyle] = useState(styling);

return (
        <RadioButtonGroup
            onChange={(event) => {
                setStyle({ ...style, font: { align: event.target.value } });
                console.log(style);
            }}
        />);

Lorsque je console.log style je reçois simplement {"font":{"align":"left"}} arrière. Je m'attendais à voir l'objet entier avec la valeur mise à jour pour align. Je suis nouveau dans la déstructuration, alors qu'est-ce que je fais mal ici?

5
codemon

C'est ton erreur

setStyle({
    ...style,
    font: { align: event.target.value } // This code replace the font object
});

Pour conserver toutes les valeurs des objets font, vous pouvez faire comme ceci

const onChange = (event) => {
    const s = {...style};
    s.font.align = event.target.value;
    setStyle(s);
}

Ou

const onChange = (event) => {
    setStyle({ 
        ...style,
        font: {
            ...style.font, // Spread the font object to preserve all values
            align: event.target.value
        }
    });
}
0
tolotra

Premièrement: const { ...styling } = styles; Est identique à: const styling = styles;

Mais vous pouvez ignorer cela complètement, utilisez simplement [...] = useState(styles)

setStyle() accepte une fonction qui reçoit l'état actuel, dans votre style de cas. Vous pouvez donc utiliser l'opérateur d'étalement ... Pour créer un nouvel objet et y ajouter des valeurs.

setStyle(style => ({ ...style, font: { ...style.font, align: event.target.value } ) ) );

Le code ci-dessus utilise la fonction Flèche, cela pourrait également être écrit comme une fonction normale, mais probablement plus facile à comprendre:

setStyle( function (style) {
    return  {
        ...style,
        font: {
            ...style.font,
            align: 'center'
        }
    }
});

Votre console.log Dans setStyle affiche le style actuel, car le style modifié sera vu lors du prochain rendu. J'ai donc déplacé le console.log Avant de revenir.

const [style, setStyle] = useState(styles);

console.log(style);

return (
        <RadioButtonGroup
            onChange={(event) => {
                setStyle(style => ({ ...style, font: { ...style.font, align: event.target.value } ) ) );
            }}
        />);

Voici quelques liens pour vous aider à comprendre tout cela:

0
user3414333

Votre code pour useState par défaut n'est pas valide. Vous devez écrire comme ci-dessous pour useState par défaut:

  const { ...styling } = styles;
  const [style, setStyle] = useState({ styling }); // styling should be use in {}

return (
        <RadioButtonGroup
          onChange={event => {
            setStyle({
              ...styling,
              font: { ...styling.font, align: event.target.value }
            });
            console.log(style);
          }}
        />);

Démo: consultez cette démo avec console.log.

Edit awesome-diffie-pflqz

0