如何使用生命周期方法 getDerivedStateFromProps 而不是 componentWillReceiveProps
How to use lifecycle method getDerivedStateFromProps as opposed to componentWillReceiveProps
看起来 componentWillReceiveProps
将在即将发布的版本中完全淘汰,取而代之的是新的生命周期方法 getDerivedStateFromProps
:static getDerivedStateFromProps().
经检查,您现在似乎无法像在 componentWillReceiveProps
中那样直接比较 this.props
和 nextProps
。有什么解决办法吗?
此外,它现在 return 是一个对象。我假设 return 值本质上是 this.setState
是否正确?
下面是我在网上找到的例子:State derived from props/state.
之前
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;
}
}
关于 componentWillReceiveProps
的删除:您应该能够结合使用 getDerivedStateFromProps
和 componentDidUpdate
来处理它的使用,请参阅 the React blog post 以了解迁移示例。是的,getDerivedStateFromProps
返回的对象更新状态类似于传递给 setState
的对象。
如果你真的需要一个 prop 的旧值,你总是可以用这样的东西将它缓存在你的状态中:
state = {
cachedSomeProp: null
// ... rest of initial state
};
static getDerivedStateFromProps(nextProps, prevState) {
// do things with nextProps.someProp and prevState.cachedSomeProp
return {
cachedSomeProp: nextProps.someProp,
// ... other derived state properties
};
}
任何不影响状态的东西都可以放在 componentDidUpdate
中,甚至还有 getSnapshotBeforeUpdate
非常 low-level 的东西。
更新:要了解新的(和旧的)生命周期方法,react-lifecycle-visualizer 包可能会有所帮助。
因为我们recently posted on the React blog,在绝大多数情况下你根本不需要getDerivedStateFromProps
.
如果您只想计算一些派生数据,可以:
- 就在里面做吧
render
- 或者,如果重新计算它很昂贵,请使用像
memoize-one
这样的记忆助手。
这是最简单的 "after" 示例:
import memoize from "memoize-one";
class ExampleComponent extends React.Component {
getDerivedData = memoize(computeDerivedState);
render() {
const derivedData = this.getDerivedData(this.props.someValue);
// ...
}
}
查看 this section of the blog post 了解更多信息。
如 Dan Abramov 所述
Do it right inside render
我们实际上将这种方法与 memoise one 一起用于任何类型的代理道具来状态计算。
我们的代码看起来是这样的
// ./decorators/memoized.js
import memoizeOne from 'memoize-one';
export function memoized(target, key, descriptor) {
descriptor.value = memoizeOne(descriptor.value);
return descriptor;
}
// ./components/exampleComponent.js
import React from 'react';
import { memoized } from 'src/decorators';
class ExampleComponent extends React.Component {
buildValuesFromProps() {
const {
watchedProp1,
watchedProp2,
watchedProp3,
watchedProp4,
watchedProp5,
} = this.props
return {
value1: buildValue1(watchedProp1, watchedProp2),
value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
}
}
@memoized
buildValue1(watchedProp1, watchedProp2) {
return ...;
}
@memoized
buildValue2(watchedProp1, watchedProp3, watchedProp5) {
return ...;
}
@memoized
buildValue3(watchedProp3, watchedProp4, watchedProp5) {
return ...;
}
render() {
const {
value1,
value2,
value3
} = this.buildValuesFromProps();
return (
<div>
<Component1 value={value1}>
<Component2 value={value2}>
<Component3 value={value3}>
</div>
);
}
}
它的好处是您不需要在 getDerivedStateFromProps
或 componentWillReceiveProps
中编写大量比较样板代码,并且您可以跳过构造函数中的复制粘贴初始化。
注意:
此方法仅用于将道具代理到状态,如果您有一些内部状态逻辑,它仍然需要在组件生命周期中处理。
getDerivedStateFromProps 用于在渲染之前更新状态并使用 props
更新状态
GetDerivedStateFromPropd 借助道具值更新统计值
看起来 componentWillReceiveProps
将在即将发布的版本中完全淘汰,取而代之的是新的生命周期方法 getDerivedStateFromProps
:static getDerivedStateFromProps().
经检查,您现在似乎无法像在 componentWillReceiveProps
中那样直接比较 this.props
和 nextProps
。有什么解决办法吗?
此外,它现在 return 是一个对象。我假设 return 值本质上是 this.setState
是否正确?
下面是我在网上找到的例子:State derived from props/state.
之前
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;
}
}
关于 componentWillReceiveProps
的删除:您应该能够结合使用 getDerivedStateFromProps
和 componentDidUpdate
来处理它的使用,请参阅 the React blog post 以了解迁移示例。是的,getDerivedStateFromProps
返回的对象更新状态类似于传递给 setState
的对象。
如果你真的需要一个 prop 的旧值,你总是可以用这样的东西将它缓存在你的状态中:
state = {
cachedSomeProp: null
// ... rest of initial state
};
static getDerivedStateFromProps(nextProps, prevState) {
// do things with nextProps.someProp and prevState.cachedSomeProp
return {
cachedSomeProp: nextProps.someProp,
// ... other derived state properties
};
}
任何不影响状态的东西都可以放在 componentDidUpdate
中,甚至还有 getSnapshotBeforeUpdate
非常 low-level 的东西。
更新:要了解新的(和旧的)生命周期方法,react-lifecycle-visualizer 包可能会有所帮助。
因为我们recently posted on the React blog,在绝大多数情况下你根本不需要getDerivedStateFromProps
.
如果您只想计算一些派生数据,可以:
- 就在里面做吧
render
- 或者,如果重新计算它很昂贵,请使用像
memoize-one
这样的记忆助手。
这是最简单的 "after" 示例:
import memoize from "memoize-one";
class ExampleComponent extends React.Component {
getDerivedData = memoize(computeDerivedState);
render() {
const derivedData = this.getDerivedData(this.props.someValue);
// ...
}
}
查看 this section of the blog post 了解更多信息。
如 Dan Abramov 所述
Do it right inside render
我们实际上将这种方法与 memoise one 一起用于任何类型的代理道具来状态计算。
我们的代码看起来是这样的
// ./decorators/memoized.js
import memoizeOne from 'memoize-one';
export function memoized(target, key, descriptor) {
descriptor.value = memoizeOne(descriptor.value);
return descriptor;
}
// ./components/exampleComponent.js
import React from 'react';
import { memoized } from 'src/decorators';
class ExampleComponent extends React.Component {
buildValuesFromProps() {
const {
watchedProp1,
watchedProp2,
watchedProp3,
watchedProp4,
watchedProp5,
} = this.props
return {
value1: buildValue1(watchedProp1, watchedProp2),
value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
}
}
@memoized
buildValue1(watchedProp1, watchedProp2) {
return ...;
}
@memoized
buildValue2(watchedProp1, watchedProp3, watchedProp5) {
return ...;
}
@memoized
buildValue3(watchedProp3, watchedProp4, watchedProp5) {
return ...;
}
render() {
const {
value1,
value2,
value3
} = this.buildValuesFromProps();
return (
<div>
<Component1 value={value1}>
<Component2 value={value2}>
<Component3 value={value3}>
</div>
);
}
}
它的好处是您不需要在 getDerivedStateFromProps
或 componentWillReceiveProps
中编写大量比较样板代码,并且您可以跳过构造函数中的复制粘贴初始化。
注意:
此方法仅用于将道具代理到状态,如果您有一些内部状态逻辑,它仍然需要在组件生命周期中处理。
getDerivedStateFromProps 用于在渲染之前更新状态并使用 props
更新状态GetDerivedStateFromPropd 借助道具值更新统计值