在React / React Native中,使用构造函数和getInitialState有什么区别?

710
我曾看到两个词被交替使用。
它们各自的主要用例是什么?有什么优缺点?哪种更好?
8个回答

988

这两种方法是不可互换的。当使用ES6类时,应该在构造函数中初始化状态,并在使用React.createClass时定义getInitialState方法。

请参阅官方React文档有关ES6类的主题

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { /* initial state */ };
  }
}

等同于

var MyComponent = React.createClass({
  getInitialState() {
    return { /* initial state */ };
  },
});

注意,在构造函数中,您应该直接赋值给 this.state,而这是唯一允许的地方;其他任何地方都应该使用 this.setState(...)


10
使用setState比直接使用this.state =更好吗? - freedrull
223
在构造函数中,您应该直接给this.state赋值。请注意,这是唯一允许这样做的地方。在其他任何地方,您都应该使用this.setState() - Alexandre Kirszenberg
11
只有在使用props时,您才需要将其作为参数添加到构造函数中。类似地,在这里使用super()就可以了。 - inostia
10
React文档建议总是将props传递给super()(https://facebook.github.io/react/docs/state-and-lifecycle.html#adding-local-state-to-a-class)。但我不知道这个建议的原因。你是对的,将`props`传递给`super()`实际上并不是必要的,因为无论如何`this.props`仍然可以在`render()`和其他方法中访问。也许这个建议是为了与潜在的未来功能兼容。 - Matt Browne
5
你需要直接修改 this.state,我建议创建一个函数,接受 (state, props) 作为参数并返回新的状态,这样你可以在构造函数中使用 this.state = myFn(null, props) 或在任何其他地方使用 this.setState(myFn) - Alexandre Kirszenberg
显示剩余5条评论

180

constructorgetInitialState的区别在于ES6和ES5本身的差异。
getInitialState用于React.createClass,而
constructor用于React.Component

因此,问题归结为使用ES6或ES5的优缺点。

让我们看一下代码上的区别

ES5

var TodoApp = React.createClass({ 
  propTypes: {
    title: PropTypes.string.isRequired
  },
  getInitialState () { 
    return {
      items: []
    }; 
  }
});

ES6

class TodoApp extends React.Component {
  constructor () {
    super()
    this.state = {
      items: []
    }
  }
};

关于这个问题,Reddit上有一个有趣的帖子

React社区正在向ES6靠拢,并且这被认为是最佳实践。

React.createClassReact.Component之间存在一些区别。例如,在这些情况下如何处理this。在这篇博客文章和Facebook的自动绑定内容中了解更多关于这些差异的信息。

constructor也可以用来处理这种情况。要将方法绑定到组件实例中,可以在constructor中预先绑定。是一个很好的材料,可以做出这样酷的东西。

一些关于最佳实践的好资料
React.js组件状态的最佳实践
将React项目从ES5转换为ES6

更新:2019年4月9日

随着Javascript类API的新变化,您不需要构造函数。

您可以这样做:

class TodoApp extends React.Component {

    this.state = {items: []}
};

这仍将被转译为构造函数格式,但您不必担心它。您可以使用更易读的格式。

React Hooks图像 利用React Hooks

从React 16.8版本开始,有一个名为Hooks的新API。

现在,您甚至不需要类组件来拥有状态。这可以在功能组件中完成。

import React, { useState } from 'react';

function TodoApp () {
  const items = useState([]);

请注意,初始状态作为参数传递给useState; useState([])

阅读有关React Hooks的更多信息,请查看官方文档


区别在于您使用的 ES 版本。 - jasmo2
2
难道还有第三种构建对象的方式,作为一个功能性的“状态钩子”吗?https://reactjs.org/docs/hooks-state.html 我是React Native的新手,所以我可能错了。 - djangofan
2
嗨@djangofan,我想更新这个已经有一段时间了。感谢你推动我朝着那个方向前进。我已经使用类字段和React hooks的useState添加了新的简写方式。 - sudo bangbang
你能解释一下什么是 super(),为什么我们要将 props 作为参数传递给它们吗?@sudobangbang - DevAS

36

区别在于它们的起始点不同,constructor 是 JavaScript 类中的构造函数,而 getInitialStateReact 生命周期的一部分。

constructor 是你的类初始化的地方...

构造函数

构造函数方法是使用类创建和初始化对象的特殊方法。一个类中只能有一个名为“constructor”的特殊方法。如果类包含多个构造函数方法,则会抛出 SyntaxError。

构造函数可以使用 super 关键字调用父类的构造函数。

在 React v16 文档中,它们没有提到任何偏好,但如果你使用 createReactClass(),则需要使用 getInitialState...

设置初始状态

在 ES6 类中,您可以通过在构造函数中分配 this.state 来定义初始状态:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  // ...
}

使用createReactClass(),需要提供一个名为getInitialState的单独方法来返回初始状态:

var Counter = createReactClass({
  getInitialState: function() {
    return {count: this.props.initialCount};
  },
  // ...
});

点击此处获取更多信息。

下面的图片展示了React组件的几个生命周期:

React lifecycle


1
我建议将componentWillReceiveProps添加到图表中,因为OP是关于组件状态的。 - Pete
1
你能解释一下什么是 super(),为什么我们要将 props 作为参数传递给它们吗?@Alireza - DevAS

11

如果您正在使用ES6编写React-Native类,将遵循以下格式。它包括RN的生命周期方法,用于为该类进行网络调用。

import React, {Component} from 'react';
import {
     AppRegistry, StyleSheet, View, Text, Image
     ToastAndroid
} from 'react-native';
import * as Progress from 'react-native-progress';

export default class RNClass extends Component{
     constructor(props){
          super(props);

          this.state= {
               uri: this.props.uri,
               loading:false
          }
     }

     renderLoadingView(){
          return(
               <View style={{justifyContent:'center',alignItems:'center',flex:1}}>
                    <Progress.Circle size={30} indeterminate={true} />
                    <Text>
                        Loading Data...
                    </Text>
               </View>
          );
     }

     renderLoadedView(){
          return(
               <View>

               </View>
          );
     }

     fetchData(){
          fetch(this.state.uri)
               .then((response) => response.json())
               .then((result)=>{

               })
               .done();

               this.setState({
                         loading:true
               });
               this.renderLoadedView();
     }

     componentDidMount(){
          this.fetchData();
     }

     render(){
          if(!this.state.loading){
               return(
                    this.renderLoadingView()
               );
          }

          else{

               return(
                    this.renderLoadedView()
               );
          }
     }
}

var style = StyleSheet.create({

});

2
这些天,我们不必在组件内部调用构造函数 - 我们可以直接调用state={something:""},否则以前我们必须使用super()声明构造函数,以继承React.Component类的所有内容,然后在构造函数内初始化状态。
如果使用React.createClass,则使用getInitialState方法定义初始化状态。

0

如果有人仍在寻找答案,那么这个链接会很有帮助Link

在React中,构造函数和getInitialState都用于初始化状态,但它们不能互换使用。

我们在React.createClass中使用getInitialState,而constructor则用于React.Component。

构造函数是设置组件初始状态的理想位置。您需要直接分配初始状态,而不是在其他方法中使用setState()。

class Hello extends React.Component { 
   constructor(props) { 
   super(props); 
   this.setState({ 
  title: 'This is the first test' 
   }); 
}   
  render() { 
    return <div>{this.state.title} </div> 
  } 
}   
ReactDOM.render(<Hello />, document.getElementById('container'));

ES5和ES6之间的主要基本区别在于新的class关键字。ES5没有提供定义React组件类的便利性,而ES则提供了将React组件定义为类的便利性。
更简单的是,getInitialState是定义React组件初始状态的ES5友好方法。我们使用getInitialState与React.createClass一起使用,而constructor与React.Component一起使用。
例子:
class Goodmorning extends React.Component { 
  render() { 
    return <span>Good Morning</span>; 
  } 
}
It would rely on helper module called create-react-class: 
var createGoodmorningReactClass = require('create-react-class'); 
var Goodmorning = createReactClass({ 
  render: function() { 
    return <span>Good Morning</span>; 
  } 
}); 
The object passed into create-react-class that is defined in initial stage by calling the getInitialState attribute: 
 var Goodmorning = createReactClass({ 
  getInitialState: function() { 
    return {name: this.props.name}; 
  }, 
  render: function() { 
    return <span>Good {this.state.name}</span>; 
  } 
}); 
In ES6 implementation: 
class Goodmorning extends React.Component { 
  constructor(props) { 
    super(props); 
    this.state = { 
      name: props.name 
    } 
  } 
  render() { 
    return <span>Good {this.state.name}</span>; 
  } 
} 

如果还有人在寻找答案,也可以阅读这篇文章。 链接


0

它们的不同之处在于它们从哪里出发,因此 constructor 是 JavaScript 类中的构造函数,另一方面,getInitialState 是 React 生命周期的一部分。constructor 方法是用于创建和初始化使用类创建的对象的特殊方法。


-1
在构造函数中,我们应该始终初始化状态。

1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接