React组件从props初始化状态

在React中,这两个实现之间有什么真正的区别吗? 一些朋友告诉我FirstComponent是模式,但我不明白为什么。SecondComponent似乎更简单,因为渲染只被调用一次

第一:

import React, { PropTypes } from 'react'


class FirstComponent extends React.Component {


state = {
description: ''
}


componentDidMount() {
const { description} = this.props;
this.setState({ description });
}


render () {
const {state: { description }} = this;
return (
<input type="text" value={description} />
);
}
}


export default FirstComponent;

第二:

import React, { PropTypes } from 'react'


class SecondComponent extends React.Component {


state = {
description: ''
}


constructor (props) => {
const { description } = props;
this.state = {description};
}


render () {
const {state: { description }} = this;
return (
<input type="text" value={description} />
);
}
}


export default SecondComponent;
< p >更新: 我把setState()改为this.state = {}(谢谢joews),然而,我仍然没有看到区别。哪个更好?< / p >
364135 次浏览

你不需要在组件的constructor中调用setState——直接设置this.state是习惯用法:

class FirstComponent extends React.Component {


constructor(props) {
super(props);


this.state = {
x: props.initialX
};
}
// ...
}

看到React文档-向类中添加本地状态

你描述的第一种方法没有任何优势。这将导致在第一次挂载组件之前立即进行第二次更新。

应该注意的是,它是一种反模式,用于复制永远不会改变状态的属性(在这种情况下,只需直接访问.props)。如果你有一个状态变量,它最终会改变,但以一个.props的值开始,你甚至不需要调用构造函数——这些局部变量是在调用父函数的构造函数后初始化的:

class FirstComponent extends React.Component {
state = {
x: this.props.initialX,
// You can even call functions and class methods:
y: this.someMethod(this.props.initialY),
};
}

这是一种相当于下面@joews回答的简写。它似乎只适用于最新版本的es6转译器,我在一些webpack设置中遇到过问题。如果这对你不起作用,你可以尝试添加babel插件babel-plugin-transform-class-properties,或者你可以使用下面@joews的非简写版本。

如果你想将所有的道具添加到状态中并保留相同的名称,你可以使用如下所示的简短形式。

constructor(props) {
super(props);
this.state = {
...props
}
//...
}

针对React 16.3进行更新 alpha引入了static getDerivedStateFromProps(nextProps, prevState) (文档)作为componentWillReceiveProps的替换。

getDerivedStateFromProps在组件实例化之后以及在它接收到新道具时调用。它应该返回一个对象来更新状态,或者返回null来表示新的道具不需要任何状态更新。

注意,如果父组件导致你的组件重新呈现,即使道具没有改变,这个方法也会被调用。如果您只想处理更改,则可能希望比较新的值和以前的值。

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

它是静态的,因此它不能直接访问this(但是它可以访问prevState,它可以存储通常附加到this的东西,例如refs)

编辑以反映@nerfologist在评论中的更正

如果你直接从props初始化状态,它会在React 16.5中显示警告

你可以在需要时使用key值来重置状态,传递道具来状态,这不是一个好的做法,因为你在一个地方有不受控组件和受控组件。数据应该在一个地方处理 读到这 https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key < / p >

在构造函数中像这样设置状态数据

constructor(props) {
super(props);
this.state = {
productdatail: this.props.productdetailProps
};
}

如果你通过props设置side componentDidMount()方法,它将不会工作。

你可以使用componentWillReceiveProps。

constructor(props) {
super(props);
this.state = {
productdatail: ''
};
}


componentWillReceiveProps(nextProps){
this.setState({ productdatail: nextProps.productdetailProps })
}
即使props更改为new,状态也不会改变,因为mount再也不会发生。 所以getDerivedStateFromProps存在,

class FirstComponent extends React.Component {
state = {
description: ""
};
    

static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.description !== nextProps.description) {
return { description: nextProps.description };
}
    

return null;
}


render() {
const {state: {description}} = this;


return (
<input type="text" value={description} />
);
}
}

或者使用key道具作为触发器来初始化:

class SecondComponent extends React.Component {
state = {
// initialize using props
};
}
<SecondComponent key={something} ... />

在上面的代码中,如果something改变了,那么SecondComponentre-mount作为一个新实例,而state将由props初始化。