Javascript 如何使用生命周期方法getDerivedStateFromProps而不是componentWillReceiveProps
在即将发布的版本中,Javascript 如何使用生命周期方法getDerivedStateFromProps而不是componentWillReceiveProps,javascript,reactjs,lifecycle,Javascript,Reactjs,Lifecycle,在即将发布的版本中,组件将接受props将被完全淘汰,取而代之的是一种新的生命周期方法getDerivedStateFromProps: 经检查,您现在似乎无法直接比较此.props和下一步操作,就像您在组件中将接收props一样。这有什么办法吗 此外,它现在返回一个对象。假设返回值本质上是this.setState,对吗 下面是我在网上找到的一个示例: 之前 class ExampleComponent extends React.Component { state = { der
组件将接受props
将被完全淘汰,取而代之的是一种新的生命周期方法getDerivedStateFromProps
:
经检查,您现在似乎无法直接比较此.props
和下一步操作
,就像您在组件中将接收props一样。这有什么办法吗
此外,它现在返回一个对象。假设返回值本质上是this.setState
,对吗
下面是我在网上找到的一个示例:
之前
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;
}
}
关于删除
组件WillReceiveProps
:您应该能够通过组合使用getDerivedStateFromProps
和componentDidUpdate
来处理其使用,请参见迁移示例。是的,getDerivedStateFromProps
返回的对象更新状态类似于传递给setState
的对象
如果您确实需要道具的旧值,您可以始终使用以下内容将其缓存在您的状态中:
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
};
}
任何不影响状态的内容都可以放入componentdiddupdate
,甚至还有一个getSnapshotBeforeUpdate
用于非常低级的内容
更新:要了解新的(和旧的)生命周期方法,该软件包可能会有所帮助。正如我们所说,在绝大多数情况下,您根本不需要getDerivedStateFromProps
如果您只想计算某些派生数据,请执行以下任一操作:
渲染中执行该操作
memoizeone
这样的记忆辅助工具查看了解更多信息。如丹·阿布拉莫夫所述 在渲染器内部执行此操作 实际上,我们将这种方法与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>
);
}
}
/./decorators/memonized.js
从“memoize one”导入memoizeOne;
已记忆的导出函数(目标、键、描述符){
descriptor.value=memoizeOne(descriptor.value);
返回描述符;
}
//./components/exampleComponent.js
从“React”导入React;
从'src/decorators'导入{memonized};
类ExampleComponent扩展了React.Component{
buildValuesFromProps(){
常数{
监视Prop1,
监视Prop2,
观看节目3,
观看节目4,
观看节目5,
}=这是道具
返回{
值1:buildValue1(watchedProp1,watchedProp2),
值2:buildValue2(watchedProp1、watchedProp3、watchedProp5),
值3:构建值3(watchedProp3、watchedProp4、watchedProp5),
}
}
@回忆
构建值1(watchedProp1、watchedProp2){
返回。。。;
}
@回忆
构建值2(watchedProp1、watchedProp3、watchedProp5){
返回。。。;
}
@回忆
构建值3(watchedProp3、watchedProp4、watchedProp5){
返回。。。;
}
render(){
常数{
价值1,
价值2,
价值3
}=this.buildValuesFromProps();
返回(
);
}
}
它的好处是,您不需要在getDerivedStateFromProps
或componentWillReceiveProps
中编写大量的比较样板文件,并且可以跳过构造函数中的复制粘贴初始化
注意:
此方法仅用于将道具代理到状态,如果您有一些内部状态逻辑,它仍然需要在组件生命周期中处理。getDerivedStateFromProps用于在渲染前更新状态,并使用道具条件进行更新 GetDerivedStateFromPropd在props value的帮助下更新stats值
阅读。啊,我把问题搞糟了。实际上,我的意思是
组件将接收道具
我曾想过使用我的状态保存以前的道具,但我真的想避免实现它所需的额外代码和逻辑。我会调查你提到的其他一些事情。非常感谢!对于这种难以理解的React API更改,必须在一个状态中存储以前的道具只是一个样板工作区。对于许多开发人员来说,这看起来像是一个反模式和一个回归变化。不是批评你的Oblosys,而是反应团队。@AxeEffect这是因为getDerivedStateFromProps
从来没有真正用于记忆。请看下面我的回答,我在那里描述了推荐的方法。这是打字错误吗?您是否错过了…
?那就是我们应该返回整个状态对象,还是只返回我们关心的部分。如果在绝大多数情况下都不需要,那么我很惊讶这是一个如此迫切需要的更改,它将破坏数千个工作项目。看起来React团队从工程开始。从组件将接收Props更改为getDerivedStateFromProps。它不是破坏而是强制重构所有现有代码,这非常耗时。而且似乎没有什么好处,因为你说在绝大多数情况下你根本不应该使用它。为什么要为一些本来就不应该使用的东西修改API呢?我希望Dan Abramov能对此评论做出回应。@DanAbramov有没有关于为什么要进行这种修改的答案?事实上,在我们的项目中经常使用这种方法。当新数据出现时,在屏幕上显示如snackbar之类的内容,1个示例componentWillReceiveProps
很简单,而且很有效。为什么要为了这个静态垃圾而删除它呢?标题应该是“如何在React团队竭尽全力反对它的情况下让事情运转起来”
// ./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>
);
}
}