想想一个具有道具名称的组件'和状态'过去'。
new Component(name) => "Hi {name}. It's been {elapse} seconds"
当道具{elapse}
发生变化时, {name}
应重置为0。
如果道具改变了爱丽丝'到鲍勃'在10秒钟, 消息应该从
更改爱你,爱丽丝。已经10秒了
到
嗨鲍勃。这是0秒
getDerivedStateFromProps
无法使用,因为{elapse}
不是{name}
的纯函数,我不能返回0,因为它可能会在重新渲染时被调用。
componentDidUpdate
最终会将{elapse}
更新为0,但在此之前,无效状态" Hi Bob。它已经过了0秒,并向用户显示。
可以getDerivedStateFromProps
或componentDidUpdate
实施此方案吗?
在许多情况下,状态不是道具的纯粹功能。 getDerivedStateFromProps
仅适用于无状态功能组件吗?反应是否鼓励使用无状态组件?
getDerivedStateFromProps
如何替换有状态组件中的componentWillReceiveProps
?
答案 0 :(得分:6)
如果你环顾四周,我会发现你并不是第一个遇到这个问题的人 - 在github 1 2 3上进行了彻底的讨论。 和hackernews here中的一个帖子。建议的解决方案是镜像您需要检查状态的道具:
state = { name: "", lastTime: Date.now() }
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.name !== prevState.name) {
return { name: nextProps.name, lastTime: Date.now() };
}
return null;
}
答案 1 :(得分:0)
设置初始状态请记住我们传递的道具是{ name:'alice' }
。但是为了让getDerivedStateFromProps
能够看到名称是否已更改,我们必须在我们的状态中镜像它并使用prevState.name
访问它。我们无法在生命周期方法中使用this
,因为getDerivedStateFromProps
是pure
。
state = {time: 0, endtime: 0, name:'' }
当组件安装时,将时钟设置为每秒开始递增1。
componentDidMount() {
this.setClock();
}
当组件卸载clearInterval
componentWillUnmount() {
clearInterval(this.clockCall)
}
setInterval
每秒会调用incrementClock
,每1000毫秒(1秒)将计时器增加1。
setClock = () => {
this.setState({time: 0})
this.clockCall = setInterval(() => {
this.incrementClock();
}, 1000)
}
这是我们设置时间状态并每秒递增的地方。
incrementClock = () => {
this.setState((prevstate) => {time: prevstate.time + 1 })
}
如果名称发生变化,我们会将时间保存在一个名为endtime
的新状态中,这就是我们用来显示hey alice its been ${this.state.endtime} seconds
的时间,我们还将计时器重置为0.
static getDerivedStateFromProps(nextProps, prevState) {
if(prevState.name !== nextProps.name)
return { time: 0, endtime:prevState.time };
return null;
}
以下是使用getDerivedStateFromProps
与componentWillRecieveProps
在
class ExampleComponent extends React.Component {
state = {
derivedData: computeDerivedState(this.props)
};
componentWillReceiveProps(nextProps) {
if (this.props.someValue !== nextProps.someValue) {
this.setState({
derivedData: computeDerivedState(nextProps)
});
}
}
}
之后
class ExampleComponent extends React.Component {
// Initialize state in constructor,
// Or with a property initializer.
state = {};
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.someMirroredValue !== nextProps.someValue) {
return {
derivedData: computeDerivedState(nextProps),
someMirroredValue: nextProps.someValue
};
}
// Return null to indicate no change to state.
return null;
}
}
答案 2 :(得分:0)
我知道这里已经有了一个可以接受的答案,并且在某些情况下,可能需要将props镜像到状态,但是在您的情况下,我认为您实际上是希望使组件成为“带钥匙的不受控制的组件”如此处所述:https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key
然后,您将像这样使用它:
<Component key={name} name={name}/>
每次更新名称时,它将呈现Component的新实例,因此将重新启动计数器。
答案 3 :(得分:-1)
从版本16.3开始,更新状态以响应props更改的推荐方法是使用新的静态getDerivedStateFromProps生命周期。 (在创建组件时以及每次收到新道具时都会调用该生命周期): 见:[link] https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html