[英]React component initialize state from 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;
更新:我將 setState() 更改為 this.state = {} (感謝 joews),但是,我仍然沒有看到區別。 一個比另一個更好嗎?
應該注意的是,復制永遠不會更改為狀態的屬性是一種反模式(在這種情況下直接訪問 .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
調用setState
- 直接設置this.state
是慣用的:
class FirstComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
x: props.initialX
};
}
// ...
}
您描述的第一種方法沒有任何優勢。 它將在第一次安裝組件之前立即進行第二次更新。
React 16.3 alpha 的更新引入了static getDerivedStateFromProps(nextProps, prevState)
( docs ) 作為componentWillReceiveProps
的替代品。
getDerivedStateFromProps 在一個組件被實例化之后以及當它接收到新的 props 時被調用。 它應該返回一個對象來更新狀態,或者返回 null 來表示新的 props 不需要任何狀態更新。
請注意,如果父組件導致您的組件重新渲染,即使 props 未更改,也會調用此方法。 如果您只想處理更改,您可能想要比較新值和以前的值。
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
它是靜態的,因此它不能直接訪問this
(但是它可以訪問prevState
,它可以存儲通常附加到this
東西,例如refs
)
編輯以反映@nerfologist 在評論中的更正
如果您想將所有道具添加到狀態並保留相同的名稱,您可以使用如下的簡短形式。
constructor(props) {
super(props);
this.state = {
...props
}
//...
}
當您從構造函數中的props
初始化state
時,您必須小心。 即使props
變成新的,狀態也不會改變,因為 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
props作為觸發器來初始化:
class SecondComponent extends React.Component {
state = {
// initialize using props
};
}
<SecondComponent key={something} ... />
在上面的代碼中,如果有something
改變,那么SecondComponent
將作為一個新實例重新掛載, state
將被props
初始化。
像這樣在構造函數中設置狀態數據
constructor(props) {
super(props);
this.state = {
productdatail: this.props.productdetailProps
};
}
如果你通過 props 在 side componentDidMount()
方法中設置,它就不會工作。
如果你直接從 props init state,它會在 React 16.5(2018 年 9 月 5 日)中顯示警告
您可以在需要時使用key
重置狀態,將道具傳遞給狀態這不是一個好習慣,因為您在一個地方有不受控制和受控的組件。 數據應該在一個地方處理閱讀這個https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a -鍵
您可以使用 componentWillReceiveProps。
constructor(props) {
super(props);
this.state = {
productdatail: ''
};
}
componentWillReceiveProps(nextProps){
this.setState({ productdatail: nextProps.productdetailProps })
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.