簡體   English   中英

React組件從道具初始化狀​​態

[英]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 文檔 - 將本地狀態添加到類

您描述的第一種方法沒有任何優勢。 它將在第一次安裝組件之前立即進行第二次更新。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM