我尝试使用React钩子setState()来设置状态,使用组件接收的props。我尝试使用下面的代码:
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;
问题是组件加载时状态是设置好的,但是收到新的 prop 时状态没有更新,这种情况下如何更新状态呢?
8条答案
按热度按时间5q4ezhmt1#
useState
挂钩函数参数只使用一次,而不是每次属性更改时都使用。必须使用useEffect
挂钩来实现所谓的componentWillReceiveProps/getDerivedStateFromProps
功能km0tfn4u2#
useState(props)
中的props
值仅在初始渲染期间使用,进一步的状态更新使用设置器setNameState
完成。此外,在更新derived state时不需要
useEffect
:来自React文件:
[...]你可以在渲染过程中更新状态正确**。React将在退出第一次渲染后立即 * 重新运行状态更新后的组件**,因此成本不会很高。
[...]渲染期间的更新正是X1 M4 N1 X在概念上一直以来的样子。
本质上,我们可以通过消除额外的浏览器重绘阶段来优化性能,因为
useEffect
总是在渲染提交到屏幕之后运行。工作示例
这是一个人为的例子来说明上面的模式--在真实的代码中,你可以直接读取
props.name
。有关更合适的派生状态用例,请参见React blog post。x一个一个一个一个x一个一个二个x
gudnpqoy3#
这一大致思路可以归纳为:
ghg1uchk4#
为此,你需要使用
useEffect
,这样你的代码看起来就像。因为你想避免在pros没有改变的情况下再次重新渲染,所以你必须首先检查useEffect,然后将props设置为current变量。Demo
7gcisfzg5#
根据Hooks react文档,当任何props更新或component更新时,useEffect都会被调用,所以你需要在更新useState之前检查条件,然后更新你的值,这样它就不会不断地重新渲染
zbsbpyhn6#
我想了一个避免
useEffect
的替代解决方案。相反,它使用两个useState
。我为您将其放入一个自定义挂钩中:主要的好处是,现在通常由
useEffect
触发的重新呈现发生在任何子组件被重新呈现之前,所以这会更快。免责声明:我还没有测试这个。我做了一些谷歌搜索,发现这篇支持文章:https://pretagteam.com/question/in-react-hooks-when-calling-setstate-directly-during-render-is-the-rerender-guaranteed-to-run-before-the-render-of-children
vvppvyoh7#
如果需要从 prop 和其他状态计算状态**,而不需要额外的重新渲染**,请考虑:
a)使用
useMemo
吊钩。B)如果不是很重,计算内部抹灰:
c)对于需要比较prev props并且应该能够从另一个地方更新state的困难情况,可以使用refs,尽管看起来不太好:
型
6ju8rftf8#
我相信这个问题表明有人试图使用一个或一组概念上的变量来做两件不同的事情,例如试图让
props.name
和name
做同样的事情。所以如果
这还不够,您发现自己试图将
props.name
强制到函数后面的状态变量name
中,然后可能name
被重载。尝试设置另一个状态变量-例如updatedName
,看看是否效果更好。原始示例没有演示这个问题,因为状态变量除了在日志语句中使用之外,从不使用。
如果
const [name, setName] = useState(props.name)
在每次重新呈现时更新,则具有状态变量name
将没有意义,因为它将总是与props.name
相同(并且进一步尝试改变它将导致重新呈现)。