Props vs State

133 阅读3分钟

Props

props被传递到组件中 这是一个示例(来自的React Guide代码)

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
const element = <Welcome name="Sara" />;

示例代码中的<Welcome name="Sara" />创建了一个name具有 value的属性"Sara"。这里看起来其实有点相像是函数调用...

属性被传递给组件,类似于如何将参数传递给函数。事实上我们确实可以将组件用函数方式重写,这是定义一个组件Component最简单的方式。如下所示:

function Welcome(props) {
    return <h1>Hello {props.name}</h1>;
}

一个组件即使没有传递props它仍然可以通过给组件添加defaultProps来设置可选的props:

class Welcome extends React.Component {
  render() {
    return <h1>Hello {this.props.name}</h1>;
  }
}

Welcome.defaultProps = {
  name: "world",
};

所以说组件的props既可以来自于父级,也可以由组件本身设置。

关于props最后需要注意的一点,它不应该被改变!在组件的生命周期中props不应更改。我们可以将任何仅使用props的React组件视为“纯”组件,也就是说在给定相同输入的情况下,它将始终呈现相同的输出。

State

Props,State都是保存有关组件的信息,但这两者信息处理方式是不同的。

当组件需要在渲染之间跟踪某些信息,利用State我们就可以在组件中创建、更新、使用我们希望得到的信息。

我将使用一个相当简单的组件来查看state的实际工作方式,通过一个按钮来记录点击它的次数:

class Button extends React.Component {
  constructor() {
    super();
    this.state = {
      count: 0,
    };
  }

  updateCount() {
    this.setState((prevState, props) => {
      return { count: prevState.count + 1 }
    });
  }

  render() {
    return (<button
              onClick={() => this.updateCount()}
            >
              Clicked {this.state.count} times
            </button>);
  }
}

通过这个例子,我们可以看到props和state的第一个真正区别是:

1. state在组件中创建

constructor() {
  super();
  this.state = {
    count: 0,
  };
}

constructor构造函数是state获取初始数据的地方,可以自定义默认数据,也可以使用props来初始化state数据。

看似有些矛盾但也是有道理的,印证了我们不能改变props的,如果你想要将组件接收到的数据做一些处理时,就可以将props值初始化给state然后更新state值并使用state。

2. state是多变的

updateCount() {
  this.setState((prevState, props) => {
    return { count: prevState.count + 1 }
  });
}

我们通过更改状态count来跟踪按钮点击次数。setState是非常重要的,首先可以看到setState接收来一个函数,这里是因为setState可以异步运行,它需要一个回调函数而不是直接更新状态。我们可以在回调中访问prevState,这里包含以前的状态信息。

setState更新状态对象并自动重新渲染组件,我们不需要担心重复渲染问题,react会处理这一切!react会在很多情况下静默的使用state的批更新机制使得性能得到保证。

⚠setState警告1:

// 不要这样做!
this.state.count = this.state.count + 1

React无法监听以这种方式更新的状态,因此您的组件不会重新渲染。你应该使用setState

⚠setState警告2:

// 不要这样做!
this.setState({
  count: this.state.count + 1
});

虽然这看起来很合理,也不会引发错误跑抛出,但这是错误的用法。这里没有考虑到异步特性,可能会导致数据的不同步。

现在我们来看一下完整流程:

  1. 组件已初始化state.count设置为0
  this.state = {
    count: 0,
  };
  1. 组件显示为,“Clicked 0 times” 作为按钮的文本
Clicked {this.state.count} times
  1. 用户点击按钮
  2. updateCount被调用,方法绑定到组件的这个实例上
onClick={() => this.updateCount()}
  1. updateCount通过回调调用setState在先前状态的值上增加
this.setState((prevState, props) => {
  return { count: prevState.count + 1 }
});
  1. setState触发render,组件呈现 “Clicked 1 times” 作为按钮文本
Clicked {this.state.count} times

小结

虽然propsstate两者都保存着与组件有关的信息,但它们的使用方式不同,应该分开保存。

props包含父组件设置的信息(也可以自己设置默认值)并不应该更改。

state包含组件自己出实话、更改和使用的私有信息。保留的是一种在交互过程中,随时间变化的数据

本文内容包含引用和来源: 来源1来源2