ReactJS: Props与State区别

摘要

propsstate的差别是React新手最常问到的问题?它们貌似相似,但用法其实完全不同。那它们的区别是什么呢?

Props

“props”是什么意思呢?其实就是"properties"的缩写。它有什么特点呢?

props是被传入组件的

看个React Guide里的例子

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

const element = <Welcome name="Sara" />;

你可以在CodePen上体验上面代码片的效果。

<Welcome name="Sara" />这行表示,创建的组件带有属性name,值为"Sara"

这听起来有点像函数调用哎…
没错,属性被传入组件中,就如同参数被传入一个函数。事实上,我们也可以重写上面组件:

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

现在看更明显了:

props就如同参数一样

那么props应该是从上层(组件)传递来的吧?
经常如此,但不总是。一个组件也可包含带默认值的props,这样如果props 没有传进来,依然可以设置它的值。
上面的例子中,如果我们在Welcome组件中,给name属性加一个defaultProps,这个属性就不是必填的了:

class Welcome extends React.Component {
  render() {
    return <h1>Hello {this.props.name}</h1>;
  }
}
// 定义默认属性值
Welcome.defaultProps = {
  name: "world",
};

现在,如果调用Welcome组件且没传name属性,它就会渲染为<h1> Hello world</h1>

props可以来自父组件,也可以被自身设置

不应该改变props的值

什么?!我早就这么做了…
早期React版本提供了setPropsreplaceProps用来改变props的值,但这最近的版本这些方法早就被标记为deprecated(不推荐使用)。在组件的生命周期中,props不应该被更改。
好吧,我不会再改props了。
由于props是被传入的,并且不能改变,你可以认为React组件只使用了“纯净”(pure)的props。也就是,传入相同的props,渲染出的一定不会变。这使得组件很容易被测试。

State

除了propsstate也包含了组件的数据。然而,数据的类型和如何操作时不同的。
一个组件默认是没有状态的,例如上面例子中的Welcome就是无状态的

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

那什么时候会使用状态呢?
如果一个组件需要追踪渲染时自己生成和更新的信息时,就用到了状态。
我们通过一个简单的组件,看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>);
  }
}

你可以再CodePen上试一下效果。
使用state后代码复杂了好多。不用担心我们现在分解一下上面的代码,让它更好懂。
propsstate的第一个区别:

state是在组件中生成的

我们看下构造函数constructor

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

在这里,state被初始化,初始化的值可以像上面一样硬编码,也可以来自于props的值。
等等,这好像有点让人困惑
我知道,但这其实很合理-你不能改变props的值,但你对组件接收的数据做些加工时很合理需求,这也是需要state的地方。
我们看下第二个区别:

state的值是可变的

看下updateCount函数:

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

我们更改状态以跟踪总点击次数。这里的关键是setState方法。首先,注意setState方法接收一个函数作为参数,因为它可能是异步执行的。它需要一个回调函数,而不是立刻更新状态。你可以看到回调函数中,我们可以访问preState,它包含了更改之前的状态。
但是setState所做的不止是更新状态,React还让它自动重新渲染了当前的组件,真是爽!

setState注意事项一

不要尝试写this.state.count = this.state.count + 1这样的语句。这种方式React不会监听状态的更新,因此组件不会自动渲染。总是使用setState来更新状态。

setState注意事项二

可能有人这么写:

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

尽管这样写看着没问题,也不会报错,而且你可能发现很多网上的例子也是这么写的。但是,这样写是不对的。因为这样写没有考虑到setState是异步的,可能会导致状态数据不同步的错误。
程序的最后一段,render方法:

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

onClick={() => this.updateCount()}意思是当按钮被点击时会调用updateCount方法。这里使用了ES6箭头函数,ES5中写法是:onClick={this.updateCount.bind(this)}
按钮中,被渲染的文本是Clicked {this.state.count} times,它将会显示this.state.count的数值.
总结一下,整个过程是这样的:
1, 组件被构建,state.count被初始化为0

  this.state = {
    count: 0,
  };

2, 组件被渲染,此时按钮上显示的是"Click 0 times"

Clicked {this.state.count} times

3,用户点击按钮
4,updateCount被调用,它绑定了组件的实例

onClick={() => this.updateCount()}

5,updateCount调用setState,后者的回调函数将原来的count状态值加1

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

6,setState触发当前组件调用其自身的render函数
7,组件被再次渲染,按钮上文本变为“Clicked 1 times”

Clicked {this.state.count} times

回顾

虽然propsstate都用来保存组件相关数据,但他们使用很不相同,应该被区分开来。

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

state包含的是组件私有的信息,被组件产生改变,用于自身。

props是从父组件向子组件传递数据的一种方式…State只用于保留交互,也就是随时间变化的数据

-来自Facebook的React Guide

原文链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值