Как синхронизировать реквизиты в состояние с помощью React hook: setState()

Я пытаюсь установить состояние с помощью React-хука setState(), используя реквизиты, которые получает компонент. Я пытался использовать следующий код:

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;

Проблема в том, что состояние устанавливается при загрузке компонента. Но когда он получает новые реквизиты, состояние не обновляется. Как обновить состояние в этом случае? Заранее спасибо.

Ответ 1

useState Аргумент функции ловушек используется только один раз, а не каждый раз, когда изменяется реквизит. Вы должны использовать ловушки useEffect для реализации того, что вы бы назвали функциональностью componentWillReceiveProps/getDerivedStateFromProps

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;

Ответ 2

Для этого вам нужно использовать useEffect чтобы ваш код выглядел следующим образом. Так как вы хотите избежать повторного рендеринга, если плюсы не изменились, вы должны сначала проверить useEffect, а затем установить для реквизитов текущую переменную.

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;

демонстрация

Ответ 3

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;

Согласно документу "Реакция хуков", все время, когда какой-либо реквизит обновляется или есть какое-либо обновление в компоненте, тогда вызывается useEffect. Таким образом, вам нужно проверить условие перед обновлением useState, а затем обновить свое значение, чтобы оно не выполняло повторную визуализацию

Ответ 4

Эту общую идею можно поставить на крючок:

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 (...);
}