如何使用 React hooks 将 props 同步到 state: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;

问题是在加载组件时设置状态。但是当它收到新的道具时,状态并没有得到更新。在这种情况下如何更新状态?提前致谢。

原文由 METALHEAD 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

useState hooks 函数参数仅使用一次,而不是每次道具更改时使用。您必须使用 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;

原文由 Shubham Khatri 发布,翻译遵循 CC BY-SA 4.0 许可协议

props 中的值 useState(props)在初始渲染期间 使用,进一步的状态更新通过设置器完成 setNameState

此外,更新 派生状态 时不需要 useEffect

 const Person = props => {
  const [nameState, setNameState] = useState(props.name);
  // update derived state conditionally without useEffect
  if (props.name !== nameState) setNameState(props.name);
  // ... other render code
};

来自 React 文档

[…] 你可以 在渲染过程更新状态。 React 将 在退出第一次渲染后 立即 重新运行 具有更新状态的组件,因此它不会很昂贵。

[…] 渲染期间的更新正是 getDerivedStateFromProps 在概念上一直是这样的。

本质上,我们可以通过摆脱额外的浏览器重绘阶段来优化性能,因为 useEffect 始终在渲染提交到屏幕后运行。

工作示例

这是一个说明上述模式的人为示例 - 在实际代码中,您将直接阅读 props.name 。有关更合适的派生状态用例,请参阅 React 博客文章

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

  return (
    <p>
      <h3>Person</h3>
      <div>{nameState} (from derived state)</div>
      <div>{props.name} (from props)</div>
      <p>Note: Derived state is synchronized/contains same value as props.name</p>
    </p>
  );
};

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

  return (
    <div>
      <Person 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>

原文由 ford04 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进