查看原文
其他

[React启蒙系列]React 组件状态

2016-09-18 lindazhang102 前端圈

本章由lindazhang102翻译

组件状态是什么?

大多数组件只拥有属性和可渲染性。然而,它还可以提供状态这个特性,状态被用来存储组件在某段时间内状态改变的信息。用户事件或系统事件会导致一些典型的状态改变。(比如,对用户输入的回应,服务器的请求, 生命周期函数)


React 文档是这样解释 state 的:

组件事件处理中用到的数据发生改变时会触发 UI 更新。在现实的 app 中,这个数据趋向于很小,并且被 JSON 化。构建一个有状态的组件的时候,要想办法用最少的属性来代表这个状态的可能性,然后把这些属性存储在 this.state 中。你会发现以这种方式考虑而书写出来的 app 将是一个最正确的 app,因为给 state 添加过多的数据或已计算出的数据意味着你需要明确地保持 UI 状态和这些数据同步,而不是依赖 React 计算给你(也就是不能充分利用 React 的 state 机制了)。


关于 React 组件的 state,需要记住以下几点:

1、如果一个组件有状态,那么它的默认状态是通过 getInitialState() 来提供的;

2、状态改变指得就是你会如何开启一个组件和它的子子孙孙组件的重渲染;

3、可以通过 this.setState() 去设置一个新 state 来告知组件 state 的改变;

4、状态改变会将新数据和该 state 里原来保存的老数据合并在一起;

5、状态改变时组件内部会进行重新渲染。不需要你再次调用 this.render()

6、state 对象只存储渲染 UI 需要的最少的数据。不要往 state 对象里放已计算的数据,别的 React 组件,或者 props。

State 如何进行工作

组件 state 工作是这样的:先给组件设置一个默认状态,再获取当前状态,最后更新这个状态。

在下面的代码示例中,我创建了一个组件 <MoodComponent />,它示范了 getInitialStatethis.state.[STATE] 和 this.setState() 是如何使用的。如果你在浏览器上点击这个组件,它会在提供的这些状态中循环。从代码中可以看出,这个组件有 3 个潜在状态和 UI 绑定在一起,至于呈现哪一种状态则取决于用户的点击。

Babel:

var MoodComponent = React.createClass({  getInitialState: function() {
   return {mood: ':|'};  },  changeMood:function(event,a){
   const moods = [':)',':|',':('];
   const current = moods.indexOf(event.target.textContent);
   this.setState({mood: current === 2 ? moods[0] : moods[current+1]});  },  render: function() {
   return (
       <span style={{fontSize:'60',border:'1px solid #333',cursor:'pointer'}}              onClick={this.changeMood}>                {this.state.mood}
       </span>        )    } }); ReactDOM.render(< MoodComponent / >, app);

HTML:

<div id="app"></div>

可以看到 <MoodComponent /> 有一个初始状态 ‘:|' ,它是通过 getInitialState: function() {return {mood: ‘:|'};} 设置的,组件第一次渲染的时候, {this.state.mood} 写的就是它。

为了改变 state,添加了一个事件监听;在这个示例中,<span> 节点添加了点击事件(onClick),它会调用 changeMood 函数。在这个函数里,我基于当前的 mood/state ,使用 this.setState() 去循环出下一个 mood。在 state 更新后,组件自己会进行重新渲染, UI 发生改变。

State vs. Props

state 和 props 的共同之处:

1、都是简单的 JS 对象;

2、都有默认值;

3、都能通过 this.props 或 this.state 来读取,而且都不能用这种方式来设置值;使用 this. 时,它们都是只读的。

不同之处:

Props:

1、Props 是由它的祖上传到当前组件中的,祖上或者是父母,也可能是 React 最初渲染时的初始域;

2、Props 作为配置值传给组件。类似把参数传给函数;

3、组件接收的时候, Props 是不可变的。也就是说,在组件内部,不能改变传递给组件的 Props。

State:

1、State 是和 UI 绑定的某一时间点上的序列化数据代表;

2、State 都是从默认值开始,然后通过使用 setState() 进行内部改变;

3、State 只能被含有状态特性的组件修改。从这点上来看它是私有的;

4、不能更改子组件的状态。组件永远不会共享可变的状态;

5、State 只包含代表 UI 状态的最少量的数据。不包含已计算的数据,其他的 React 组件和从 props 复制来的数据;

6、如果可能的话,尽量避免使用 State 。无状态组件是理想化的,有状态组件增加了复杂度。React 文档这样建议:创建无状态组件的一般模式只是渲染数据,有状态组件高于它一个层级,通过 props 传递状态给它的子组件。有状态组件压缩了所有的交互逻辑,而无状态组件以一种声明方式来关注渲染的数据。

创建有状态函数组件

当一个组件只有孤单的 props ,没有 state 时,组件可以被写成纯函数,从而避免了创建组件实例的需要。在下面代码示例中,MyComponent 是一个函数,返回从 React.createElement() 得到的结果。

Babel:

var MyComponent = function(props){
 return <div>Hello {props.name}</div>;
};

ReactDOM.render(<MyComponent name="doug" />, app);

HTML:

<div id="app"></div>

不用 JSX 的话,上面的代码会是这个样子:

var MyComponent = function MyComponent(props) {
   return React.createElement(
       "div",
       null,
       "Hello ",        props.name    ); }; ReactDOM.render(React.createElement(MyComponent, { name: "doug" }), app);

构建一个没有调用 React.createClass() 的 React 组件被称为无状态函数组件。


无状态函数组件不能被传递组件选项(rendercomponentWillUnmount 等等)。然而,.propTypes 和.defaultProps 在函数中可以被作为属性设置。

下面代码示范了如何在无状态函数组件中设置 .propTypes 和 .defaultProps

Babel:

var MyComponent = function(props){
   return <div>Hello {props.name}</div>;
}; MyComponent.defaultProps = {name:"John Doe"}; MyComponent.propTyes = {name: React.PropTypes.string}; ReactDOM.render(<MyComponent />, app);

HTML:

<div id="app"></div>

本节笔记

  • 制作组件时,尽最大可能将你的组件制作成无状态的。



【React启蒙系列文章】

一、[React启蒙系列] 初探React

二、[React启蒙系列] 学习React前需要理解的名词

三、[React启蒙系列] React和Babel的基本使用

四、[React启蒙系列]React节点

五、[React启蒙系列]使用JSX

六、[React启蒙系列]React 组件属性


【您可能感兴趣的文章】

一、手把手教你用react

二、React入门及资源指引

三、利用ESLint检查代码质量

四、构建一个安全的 JavaScript 沙箱

五、入门Webpack,看这篇就够了

六、第三届CSS大会广州找场地啦~~求介绍~~

七、Web Components 是个什么样的东西

八、JavaScript 被忽视的细节

九、[心得] 如何提高 React App 的性能

十、[心得] 自己动手打造 ES7 开发环境

十一、[译文] 如何运用新技术提升网页速度和性能



前端圈--打造专业的前端技术会议

为web前端开发者提供技术分享和交流的平台

打造一个良好的前端圈生态,推动web标准化的发展

官网:http://fequan.com

微博:fequancom | QQ群:41378087


长按二维码关注我们

投稿:content@fequan.com

赞助合作:apply@fequan.com

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存