componentWillReceiveProps 与 getDerivedStateFromProps
componentWillReceiveProps vs getDerivedStateFromProps
componentWillReceiveProps 和 getDerivedStateFromProps 到底是什么对我来说是个微妙的问题。因为,我在使用 getDerivedStateFromProps 时遇到了一个问题:
// Component
state = {
myState: []
}
// Using this method works fine:
componentWillReceiveProps(nextProps) {
this.setState({
myState: nextProps.myPropsState
})
}
// But using this method will cause the checkboxes to be readonly:
static getDerivedStateFromProps(nextProps,prevProps) {
const { myPropsState: myState } = nextProps
return {
myState
}
}
// And here's checkbox
<input type="checkbox" id={`someid`}
onChange={(e) => this.handleMethod(e, comp.myState)}
checked={myState.indexOf(comp.myState) > -1} />
反应版本:16.4.1
getDerivedStateFromProps
不是 componentWillReceiveProps
的直接替代,纯粹是因为它在每次更新后调用,无论是状态变化还是道具变化或父级的重新渲染.
但是无论如何,简单地从getDerivedStateFromProps
返回state是不正确的,你需要在返回值之前比较state和props。否则每次更新状态都会重置为道具并且循环继续
根据 docs
getDerivedStateFromProps
is invoked right before calling the render
method, both on the initial mount and on subsequent updates. It should
return an object to update the state, or null
to update nothing.
This method exists for rare use cases where the state depends on
changes in props over time. For example, it might be handy for
implementing a <Transition>
component that compares its previous and
next children to decide which of them to animate in and out.
Deriving state leads to verbose code and makes your components
difficult to think about. Make sure you’re familiar with simpler
alternatives:
If you need to perform a side effect (for example, data fetching
or an animation) in response to a change in props, use
componentDidUpdate
lifecycle instead.
If you want to re-compute some data only when a prop changes, use
a memoization
helper instead.
If you want to “reset” some state when a prop changes, consider
either making a component fully controlled
or fully uncontrolled
with a key instead
.
P.S. 注意 getDerivedStateFromProps 的参数是 props
和 state
而不是 nextProps
和 prevProps
要了解更多详情,
为了根据道具变化进行变化,我们需要在状态中存储prevPropsState,以便检测变化。一个典型的实现看起来像
static getDerivedStateFromProps(props, state) {
// Note we need to store prevPropsState to detect changes.
if (
props.myPropsState !== state.prevPropsState
) {
return {
prevPropsState: state.myState,
myState: props.myPropsState
};
}
return null;
}
来自 React 文档:
Note that this method is fired on every render, regardless of the cause. This is in contrast to UNSAFE_componentWillReceiveProps
, which only fires when the parent causes a re-render and not as a result of a local setState
.
每次调用 setState()
后,您都在使用当前道具有效地覆盖您的状态。因此,当您选中一个框 (e) => this.handleMethod(e, comp.myState)
时,它会假设调用 setState()
来更新复选框的选中状态。但在那之后 getDerivedStateFromProps()
将被调用( 在 render 之前)以恢复该更改。这就是为什么 unconditionally updating state from props is considered an anti-pattern.
终于,我解决了我的问题。这是一次痛苦的调试:
// Child Component
// instead of this
// this.props.onMyDisptach([...myPropsState])
// dispatching true value since myPropsState contains only numbers
this.props.onMyDispatch([...myPropsState, true])
这是因为,我有两个条件:1) 复选框更改(组件)2) 重置按钮按下(子组件)
我需要在按下重置按钮时重置状态。因此,在将状态分派给重置按钮的道具时,我使用了一个布尔值来知道它是重置后的变化。您可以使用任何您喜欢的东西,但需要对其进行跟踪。
现在,在组件中,我在调试控制台输出后发现了一些关于 componentWillReceiveProps 和 getDerivedStateFromProps 之间差异的提示。
// Component
static getDerivedStateFromProps(props, state) {
const { myPropsState: myState } = props
// if reset button is pressed
const true_myState = myState.some(id=>id===true)
// need to remove true value in the store
const filtered_myState = myState.filter(id=>id!==true)
if(true_myState) {
// we need to dispatch the changes to apply on its child component
// before we return the correct state
props.onMyDispatch([...filtered_myState])
return {
myState: filtered_myState
}
}
// obviously, we need to return null if no condition matches
return null
}
下面是我查到的控制台输出结果:
getDerivedStateFromProps 会在道具更改时立即记录
componentWillReceiveProps 仅在子传播 props 更改后记录
getDerivedStateFromProps 不响应道具更改(我的意思是示例代码中的调度更改)
componentWillReceiveProps 响应 props 变化
因此,我们需要在使用 getDerivedStateFromProps 时向子组件提供更改。
在我需要的状态下粘贴真实值的过程,因为 getDerivedStateFromProps 处理所有更改,不像 componentWillReceiveProps 仅处理子组件将更改分派给道具。
顺便说一句,您可以使用自定义 属性 来检查它是否已更改并在 getDerivedStateFromProps 时更新值,但出于某种原因我必须调整此技术。
我的措辞可能有些混乱,但我希望你能明白。
componentWillReceiveProps 和 getDerivedStateFromProps 到底是什么对我来说是个微妙的问题。因为,我在使用 getDerivedStateFromProps 时遇到了一个问题:
// Component
state = {
myState: []
}
// Using this method works fine:
componentWillReceiveProps(nextProps) {
this.setState({
myState: nextProps.myPropsState
})
}
// But using this method will cause the checkboxes to be readonly:
static getDerivedStateFromProps(nextProps,prevProps) {
const { myPropsState: myState } = nextProps
return {
myState
}
}
// And here's checkbox
<input type="checkbox" id={`someid`}
onChange={(e) => this.handleMethod(e, comp.myState)}
checked={myState.indexOf(comp.myState) > -1} />
反应版本:16.4.1
getDerivedStateFromProps
不是 componentWillReceiveProps
的直接替代,纯粹是因为它在每次更新后调用,无论是状态变化还是道具变化或父级的重新渲染.
但是无论如何,简单地从getDerivedStateFromProps
返回state是不正确的,你需要在返回值之前比较state和props。否则每次更新状态都会重置为道具并且循环继续
根据 docs
getDerivedStateFromProps
is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, ornull
to update nothing.This method exists for rare use cases where the state depends on changes in props over time. For example, it might be handy for implementing a
<Transition>
component that compares its previous and next children to decide which of them to animate in and out.Deriving state leads to verbose code and makes your components difficult to think about. Make sure you’re familiar with simpler alternatives:
If you need to perform a side effect (for example, data fetching or an animation) in response to a change in props, use
componentDidUpdate
lifecycle instead.If you want to re-compute some data only when a prop changes, use a
memoization
helper instead.If you want to “reset” some state when a prop changes, consider either making a component
fully controlled
orfully uncontrolled with a key instead
.
P.S. 注意 getDerivedStateFromProps 的参数是 props
和 state
而不是 nextProps
和 prevProps
要了解更多详情,
为了根据道具变化进行变化,我们需要在状态中存储prevPropsState,以便检测变化。一个典型的实现看起来像
static getDerivedStateFromProps(props, state) {
// Note we need to store prevPropsState to detect changes.
if (
props.myPropsState !== state.prevPropsState
) {
return {
prevPropsState: state.myState,
myState: props.myPropsState
};
}
return null;
}
来自 React 文档:
Note that this method is fired on every render, regardless of the cause. This is in contrast to
UNSAFE_componentWillReceiveProps
, which only fires when the parent causes a re-render and not as a result of a localsetState
.
每次调用 setState()
后,您都在使用当前道具有效地覆盖您的状态。因此,当您选中一个框 (e) => this.handleMethod(e, comp.myState)
时,它会假设调用 setState()
来更新复选框的选中状态。但在那之后 getDerivedStateFromProps()
将被调用( 在 render 之前)以恢复该更改。这就是为什么 unconditionally updating state from props is considered an anti-pattern.
终于,我解决了我的问题。这是一次痛苦的调试:
// Child Component
// instead of this
// this.props.onMyDisptach([...myPropsState])
// dispatching true value since myPropsState contains only numbers
this.props.onMyDispatch([...myPropsState, true])
这是因为,我有两个条件:1) 复选框更改(组件)2) 重置按钮按下(子组件)
我需要在按下重置按钮时重置状态。因此,在将状态分派给重置按钮的道具时,我使用了一个布尔值来知道它是重置后的变化。您可以使用任何您喜欢的东西,但需要对其进行跟踪。
现在,在组件中,我在调试控制台输出后发现了一些关于 componentWillReceiveProps 和 getDerivedStateFromProps 之间差异的提示。
// Component
static getDerivedStateFromProps(props, state) {
const { myPropsState: myState } = props
// if reset button is pressed
const true_myState = myState.some(id=>id===true)
// need to remove true value in the store
const filtered_myState = myState.filter(id=>id!==true)
if(true_myState) {
// we need to dispatch the changes to apply on its child component
// before we return the correct state
props.onMyDispatch([...filtered_myState])
return {
myState: filtered_myState
}
}
// obviously, we need to return null if no condition matches
return null
}
下面是我查到的控制台输出结果:
getDerivedStateFromProps 会在道具更改时立即记录
componentWillReceiveProps 仅在子传播 props 更改后记录
getDerivedStateFromProps 不响应道具更改(我的意思是示例代码中的调度更改)
componentWillReceiveProps 响应 props 变化
因此,我们需要在使用 getDerivedStateFromProps 时向子组件提供更改。
在我需要的状态下粘贴真实值的过程,因为 getDerivedStateFromProps 处理所有更改,不像 componentWillReceiveProps 仅处理子组件将更改分派给道具。
顺便说一句,您可以使用自定义 属性 来检查它是否已更改并在 getDerivedStateFromProps 时更新值,但出于某种原因我必须调整此技术。
我的措辞可能有些混乱,但我希望你能明白。