ReactJS修炼之路(三):props vs state

一,前言

初学rails和ReactJS不久,也分别在看rails和ReactJS的官方文档,至于这两者的轻重缓急,公司里带我的同事是这样说的:

“先看React的文档吧,相对rails来说,React的开发思路更绕,也可以说是React的设计思路更加新颖。”

确实,一开始上手React很容易就学会了怎么写交互性控件,能实现数据的展示和动态更新,后来发现这只是个开始。我还没形成很清晰的React组件开发思路,里面有很多很模糊的地方。下面说说我的困惑:

  • props和state的区别在哪?
  • 为什么不能直接修改props的值?

这段时间看了一些文档和博客,对这些问题有了一定的了解,props vs state这篇博客说得比较全面,特地翻译了一下,希望能帮到大家。

二,译文

从我们开始使用React在uberVU (现在是 Hootsuite)重建UI起,开发者问得最多的问题大概是:

props和state的具体区别在哪?

理解他们如何工作相当容易,特别是在对应的上下文中,但在概念上理解他们也有点困难。首先困惑着我们的是,他们都有抽象的术语和相同的值,却有着很不一样的规则。

背景

一个组件的主要责任是将原始数据转化为丰富的HTML,请记住这点。props和state共同构成原始数据,原始数据构成HTML。你可以说 props 和 state 是一个组件render()函数的输入数据,所以我们需要深入进去看看每个数据类型代表什么以及从哪里来的。

共同点

在区分props和state之前,我们先看看这两者的共同点:

  • props和state都是 纯 JS 对象
  • props和state的改变都会触发render函数来更新界面
  • props和state都是确定的。 如果你的组件在相同的props和state的组合下产生不同结果,那一定是哪里错了。

深入看看

如果一个组件需要在某个时间点改变某个属性,那该属性应设为state,否则应设为组件的prop。

props

props (properties的简称) 是一个组件的 配置选项props是由上到下指定且不可改变的。

一个组件不能改变自身的props, 但要负责设置子组件的 props

state

当组件加载时,state有一个默认值,后来state会不定期地改变(主要是用户行为触发的)。state是每一时间点组件状态的代表-快照。

一个组件在内部管理自己的state,除了设置子组件的state之外,该组件与其子组件的state没有任何联系。你可以认为state是私有的。

改变 propsstate

- props state
能否从父组件获取初始值? Yes Yes
能否被父组件改变? Yes No
能否在组件内设置默认值?* Yes Yes
能否在组件内改变? No Yes
能否设置子组件的初始值? Yes Yes
能否在子组件中改变? Yes No

*注意:propsstate 从父组件获取的初始值都会被在组件内设置的默认值覆盖。

组件是否应该有state?

state 是可选项,不是React强制实现的。因为state增加了组件的复杂度同时降低了组件的可预见性,所以没有state的组件 要略胜一筹。即便在一个交互式应用中,你显然离不开state,你也要避免有太多的有状态化组件(含有state的组件)。

组件类型


  • 无状态组件 — 只有 props, 没有 state。 除去render() 函数和所有围绕props的逻辑之外,没有什么要关心的地方。这使他们易于理解且易于测试
  • 有状态组件 — 既有 props 又有 state。也被称作状态管理者 。他们负责客户端-服务器通信(通过XHR, web sockets, 等),数据处理和给用户行为反馈。

译者标注为重要内容:这些逻辑实现应该封装在一个含有中等数量state的有状态组件中,而所有可视化和格式化的逻辑实现应该尽可能封装在多个无状态组件中。

一些讨论

  • Question about ‘props’ and ‘state’ - Google Groups
  • Thinking in React: Identify where your state should live

三,补充

补充官网文档里如何判别某一变量应设为state还是prop:

哪些组件应该有 State?

大部分组件的工作应该是从 props 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。

尝试把尽可能多的组件无状态化。 这样做能隔离 state,把它放到最合理的地方,也能减少冗余,同时易于解释程序运作过程。

常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 props 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。

哪些 应该 作为 State?

State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,想象一下表示它的状态最少需要哪些数据,并只把这些数据存入 this.state。在 render() 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,需要你经常手动保持数据同步,不能让 React 来帮你处理。

哪些不应该作为 State?

this.state 应该仅包括能表示用户界面状态所需的最少数据。因此,它不应该包括:

  • 计算所得数据: 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到 render() 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 render() 里使用 this.state.listItems.length + ’ list items’ 比把它放到 state 里好的多。
  • React 组件: 在 render() 里使用当前 props 和 state 来创建它。
  • 基于 props 的重复数据: 尽可能使用 props 来作为惟一数据来源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为未来的 props 可能会变化。

四,更多资料

  • stackoverflow上关于props和state的讨论
  • react官方文档:设计思路(中文)
  • react官方文档:设计思路(英文)

五,总结

看完上面的文章之后,我解决了几个问题:

  • props和state在使用场合的区别
  • 怎样在应用中合理区分有状态组件和无状态组件

这是第一次翻译别人的文章,我觉得要比自己看几遍理解得都要深刻,所以这是一次好的尝试。希望自己能找到更多好文章,学得更多。

你可能感兴趣的:(React)