web-dev-qa-db-fra.com

Comment synchroniser les accessoires à l'état en utilisant React hooks: setState ()

J'essaie de définir l'état en utilisant React hook setState () en utilisant les accessoires reçus par le composant. J'ai essayé d'utiliser le code ci-dessous:

import React,{useState , useEffect} from 'react';

const Persons = (props) =>  {

    // console.log(props.name);

   const [nameState , setNameState] = useState(props)

   console.log(nameState.name);
   console.log(props.name);

   return (
            <div>
                <p>My name is {props.name} and my age is {props.age}</p>
                <p>My profession is {props.profession}</p>
            </div>
        )

}

export default Persons;

Le problème est que l'état est défini lors du chargement du composant. Mais lorsqu'il reçoit de nouveaux accessoires, l'État n'est pas mis à jour. Comment mettre à jour l'état dans ce cas? Merci d'avance.

44
METALHEAD

useState l'argument de la fonction hooks n'est utilisé qu'une seule fois et non à chaque fois que l'hélice change. Vous devez utiliser les crochets useEffect pour implémenter ce que vous appelleriez le componentWillReceiveProps/getDerivedStateFromProps Fonctionnalité

import React,{useState , useEffect} from 'react';

const Persons = (props) =>  {
   const [nameState , setNameState] = useState(props)

   useEffect(() => {
       setNameState(props);
   }, [props])

   return (
            <div>
                <p>My name is {props.name} and my age is {props.age}</p>
                <p>My profession is {props.profession}</p>
            </div>
        )

}

export default Persons;
67
Shubham Khatri

Pour cela, vous devez utiliser le useEffect pour que votre code ressemble. Comme vous voulez éviter de refaire le rendu si les pros ne changent pas, vous devez d'abord vérifier sur useEffect, puis définir les accessoires sur la variable actuelle.

import React, { useState, useEffect } from "react";

const Persons = props => {
  // console.log(props.name);

  const [nameState, setNameState] = useState(props);

  console.log(nameState.name);
  console.log(props.name);
  useEffect(
    () => {
      if (nameState !== props.name) {
        setNameState(props.name);
      }
    },
    [nameState]
  );
  return (
    <div>
      <p>
        My name is {props.name} and my age is {props.age}
      </p>
      <p>My profession is {props.profession}</p>
    </div>
  );
};

export default Persons;

Démo

6
Dhaval Patel

Cette idée générale peut être mise en relation:

export function useStateFromProp(initialValue) {
  const [value, setValue] = useState(initialValue);

  useEffect(() => setValue(initialValue), [initialValue]);

  return [value, setValue];
}


function MyComponent({ value: initialValue }) {
  const [value, setValue] = useStateFromProp(initialValue);

  return (...);
}
5
bsapaka
1
gongeek
import React, { useState, useEffect } from "react";

const Persons = props => {
  // console.log(props.name);

  const [nameState, setNameState] = useState(props);

  console.log(nameState.name);
  console.log(props.name);
  useEffect(
    () => {
      if (nameState !== props) {
        setNameState(props);
      }
    },
    [nameState]
  );
  return (
    <div>
      <p>
        My name is {props.name} and my age is {props.age}
      </p>
      <p>My profession is {props.profession}</p>
    </div>
  );
};

export default Persons;

Selon le document de réaction de Hooks, tout le temps où des accessoires sont mis à jour ou toute mise à jour dans le composant est là, useEffect sera appelé. Vous devez donc vérifier la condition avant de mettre à jour useState, puis mettre à jour votre valeur afin qu'elle ne fasse pas de restitution en continu

1
Kajol Chaudhary

L'état initial transmis à useState est niquement utilisé lors du rendu initial puis ignoré, vous ne recevez donc plus de mises à jour d'état. De plus, il n'est pas nécessaire de useEffect lors de la mise à jour de l'état dérivé:

const Persons = props => {
  const [nameState, setNameState] = React.useState(props.name);
  // Here, we update derived state without useEffect
  if (props.name !== nameState) setNameState(props.name);

  return (
    <p>
      <p>Persons name</p>
      <div>{nameState} (derived state)</div>
      <div>{props.name} (props)</div>
    </p>
  );
};

const App = () => {
  const [personName, setPersonName] = React.useState("Lui");
  const changeName = () => setPersonName(personName === "Lukas" ? "Lui" : "Lukas");

  return (
    <div>
      <Persons name={personName} />
      <button onClick={changeName}>Change props</button>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>

De React docs :

vous pouvez mettre à jour l'état à droite pendant le rendu . React va réexécuter le composant avec l'état mis à jour immédiatement après avoir quitté le rendre d'abord donc ce ne serait pas cher.

une mise à jour pendant le rendu est exactement ce que getDerivedStateFromProps a toujours été comme conceptuellement.

Essentiellement, nous économisons les performances gratuitement en nous débarrassant d'une validation supplémentaire, car useEffect s'exécute sinon après que le rendu soit validé à l'écran.

0
ford04