技术控

    今日:136| 主题:49552
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] 如何存储 React 组件的数据

[复制链接]
林深处 发表于 2016-10-17 10:11:58
72 2

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
主要讲解这几个部分:state、store、static、this、module-global data
  前言

  随着 React 和 Redux 的到来,一个共同的问题被问到:
  我应该将数据保存在 Redux Store 中呢?还是应该保存成本地 state?
  其实这个问题是说的不完整( 或者原文说的太简单 ),因为你能在组件中存储数据的方式还有两种:static 和 this.(其实就是静态数据,还是类的实例数据)
  让我们来依次讨论一下,你应该在什么时候使用它们。
  一、本地 state ( Local state )

  ps:下面翻译的时候将 local state => 直接翻译成 state 吧,对于 state 其实的作用域是与组件挂钩的,直接翻译成本地 state 其实是不准确的。
  当 React 在第一次被介绍的时候,我们就知道    state。我们知道一个很重要的事情,就是当    state的值改变的时候将触发组件的 re-render(重新渲染)。  
  这个 state 也能传递给子组件,子组件中通过    props来获取传递的数据,这就允许你能够将你的组件分为:smart data-components(智能数据组件)and dumb presentational-components (填鸭式组件)。  
  这里有一个使用    state来编写的 counter app(计数 APP):  
  1. import React from 'react'
  2. class App extends React.Component {
  3.   constructor(props) {
  4.     super(props)
  5.     this.state = {
  6.       counter: 0
  7.     }
  8.     this.addOne = this.addOne.bind(this)
  9.   }
  10.   
  11.   addOne() {
  12.     this.setState({
  13.       counter: this.state.counter + 1
  14.     })
  15.   }
  16.   
  17.   render() {
  18.     return (
  19.       <div>
  20.         <button
  21.           onClick={ this.addOne }>
  22.           Increment
  23.         </button>
  24.         { this.state.counter }
  25.       </div>
  26.     )
  27.   }
  28. }
  29. export default App
复制代码
你的数据( counter 的值 )是存储在    App组件中,也能向下传递给子组件。  
  & 应用场景

  假如    counter数据在你的 app 中是很重要的,以及这个数据会存储下来用于其他组件,那么你将不希望使用    state来保存这个值。  
  这最好的实践是处理用户接口 (UI, User Interface) 的状态数据。比如:使用一个    交互组件去填写表单,这时候使用    state是不错的选择。  
  另外的例子,就是在 UI 交互相关的数据中使用,比如你将在一个列表中记录当前选中的 tab (选项卡)的状态,你就能存储一个    state。  
  在你选择    state的使用时机,也能够这样考虑:你存储的数据是否会在其他组件中使用。如果一个值是只有一个组件(或者也许只有一个子组件),这时使用    state来保持这个值(或者说状态)都是安全的。  
  总结:保持 UI 状态和暂时的数据(比如:表单的输入),能够使用    state。  
  二、Redux store

  随着发展,每个人开始选择    单向数据流, 我们选择 Redux。  
  对于 Redux,我们将获得一个全局的    store。这个 store 将绑定在一个最高等级的组件中,然后将 App 的数据流入所有的子组件(其实整个 App 就已经是这个最高等级组件的子组件了)。你能 connect 全局    store,使用:    connect wrap 和 mapStateToProps 方法.  
  首先,人们就将任何事情都交给了 Redux    store。比如:Users, modals, forms, sockets...,主要你知道的。  
  下面是一个和之前相同的计数 App,然后使用了 Redux。主要需要注意的是    counter数据,使用    mapStateToProps映射了数据,并且使用    connect方法包裹组件,    this.state.counter现在就变成了    this.props.counter,然后这个值就是通过全局    store获取的,这个全局    store将值传递给当前组件的    props。(如果想知道具体,我在    React.js 模式的文章中有介绍原理)。  
  1. import React from 'react'
  2. import { connect } from 'react-redux'
  3. import Actions from './Actions.js'
  4. class App extends React.Component {
  5.   constructor(props) {
  6.     super(props)
  7.     this.addOne = this.addOne.bind(this)
  8.   }
  9.   
  10.   addOne() {
  11.     this.props.dispatch(Actions.addOne())
  12.   }
  13.   
  14.   render() {
  15.     return (
  16.       <div>
  17.         <button
  18.           onClick={ this.addOne }>
  19.           Increment
  20.         </button>
  21.         { this.props.counter }
  22.       </div>
  23.     )
  24.   }
  25. }
  26. const mapStateToProps = store => {
  27.   return {
  28.     counter: store.counter
  29.   }
  30. }
  31. export default connect(mapStateToProps)(App)
复制代码
现在当你点击按钮的时候,通过一个 action => dispatched 使全局    store更新。然后这个数据通过外层组件传递到当前组件。  
  值得注意的是:当    props被更新的时候,这也将触发组件的 re-render(重新渲染)=> 这与你更新    state的时候一样。  
  & 应用场景

  对于 Redux    store是很好的保持了除 UI 状态数据外的应用状态。有一个不错的例子,比如用户的登录状态。对于在在登录状态改变的同时,多数组件需要访问这个数据信息做出响应。这些组件(至少有一个被渲染)将需要重新渲染与更新的信息。  
  Redux 触发事件在你需要跨组件或者跨路由的情况下是很有用的。比如有一个登录弹框,当你的 App 中有多个按钮点击都将触发弹出它的时候。而不是在你需要渲染这个弹框的多个地方做判断,你能通过一个顶层的 App 组件去使用 Redux action 去触发它并且修改    store的值。  
  总结:你想将跨组件的保持数据的时候能够使用    store。  
  三、this.<something>

  在 React 的开发中,使用    this来保存数据的场景很少。人们经常忘记了 React 使用的是 JavaScript 的 ES2015 的语法。    任何你能够用 JavaScript 做的事情,你都能在 React 做(这也是我非常喜欢 React 的原因呢 ^0^ freedom)。  
  下面的例子依然是一个计数应用,与之前的例子有点类似。
  1. import React from 'react'
  2. class App extends React.Component {
  3.   constructor(props) {
  4.     super(props)
  5.     this.counter = 0
  6.     this.addOne = this.addOne.bind(this)
  7.   }
  8.   
  9.   addOne() {
  10.     this.counter += 1
  11.     this.forceUpdate()
  12.   }
  13.   
  14.   render() {
  15.     return (
  16.       <div>
  17.         <button
  18.           onClick={ this.addOne }>
  19.           Increment
  20.         </button>
  21.         { this.counter }
  22.       </div>
  23.     )
  24.   }
  25. }
  26. export default App
复制代码
我们是在组件中使用    this存储    counter变量的值,并且使用 forceUpdate() 方法来触发组件的重新渲染。    这是因为没有任何的 state 和 props 修改,因此没有自动触发重新渲染机制。  
  这个例子实际上不应该使用    this。如果你发现你必须使用    forceUpdate()才能满足需求,你可能代码哪里出了问题。如果想值修改的时候自动触发重新渲染,你应该使用    state或者    props/Redux store(其实严格一点来说,作者这里的表述是不清的,其实重新渲染与 Redux 并无关系,本质上就是 props 的更新流入组件)。  
  & 应用场景

  使用    this来保存数据的时候,能够在改变的时候不需要去触发重新渲染的场景。比如:sockets 是很好的一个使用    this保存数据的场景。  
  1. import React from 'react'
  2. import { Socket } from 'phoenix'
  3. class App extends React.Component {
  4.   componentDidMount() {
  5.     this.socket = new Socket('http://localhost:4000/socket')
  6.     this.socket.connect()
  7.     this.configureChannel("lobby")
  8.   }
  9.   
  10.   componentWillUnmount() {
  11.     this.socket.leave()
  12.   }
  13.   
  14.   configureChannel(room) {
  15.     this.channel = this.socket.channel(`rooms:${room}`)
  16.     this.channel.join()
  17.       .receive("ok", () => {
  18.         console.log(`Succesfully joined the ${room} chat room.`)
  19.       })
  20.       .receive("error", () => {
  21.         console.log(`Unable to join the ${room} chat room.`)
  22.       })
  23.   }
  24.   
  25.   render() {
  26.     return (
  27.       <div>
  28.         My App
  29.       </div>
  30.     )
  31.   }
  32. }
  33. export default App
复制代码
大多数人们没有他们之前一直在使用    this定义方法。放你定义    render(),你实际上是:    this.prototype.render = function () { },但是这在 ES2015 的 class 语法机制下是隐式的。  
  总结:在不需要数据改变的时候去触发重新渲染机制的时候,能够使用    this去保存数据。  
  四、Static(静态的方式)

      静态方法和属性也许是最少使用的(静下来,我知道他们不是真正在 class 下的一个机制),大多数是因为他们没有被频繁使用。但是他们不是很复杂。如果你用过    PropTypes,你就定义了一个    static属性。  
  下面有两份代码块实际上是长得一样的。人们经常使用的方式是第一种,第二种是你能使用    static关键字来定义。  
  1. class App extends React.Component {
  2.   render() {
  3.     return (<div>{ this.props.title }</div>)
  4.   }
  5. }
  6. App.propTypes = {
  7.   title: React.PropTypes.string.isRequired
  8. }
复制代码
  1. class App extends React.Component {
  2.   static propTypes {
  3.     title: React.PropTypes.string.isRequired
  4.   }
  5.   
  6.   render() {
  7.     return (<div>{ this.props.title }</div>)
  8.   }
  9. }
复制代码
正如你看到的,    static并不复杂。他们是一种另外的方式去声明一个类的值。这主要的不同是    static不要像    this那样去实例化一个类再去访问值。  
  1. class App extends React.Component {
  2.   constructor() {
  3.     super()
  4.     this.prototypeProperty = {
  5.       baz: "qux"
  6.     }
  7.   }
  8.   static staticProperty = {
  9.     foo: "bar"
  10.   };
  11.   
  12.   render() {
  13.     return (<div>My App</div>)
  14.   }
  15. }
  16. const proto = new App();
  17. const proto2 = proto.prototypeProperty // => { baz: "qux" }
  18. const stat = App.staticProperty // => { foo: "bar" }
复制代码
在这个例子中,你能看获取    staticProperty的值,我们只组要直接通过类名去访问,而不是实例后。但是访问    proto.prototypeProperty就必须要    new App().  
  & 应用场景

  静态方法和属性是很少被使用,主要被用来定义工具方法或者特定类型的所有组件。
  propTypes是一个工具例子,比如一个 Button 组件,每一个按钮的渲染都需要相似的值。  
  另外个案例就是如果你关注获取的数据。如果你是使用 GraphQL 或者 Falcor,你能具体描述需要服务端返回什么数据。这种方法你能不用接受大量组件不需要的数据。
  1. class App extends React.Component {
  2.   static requiredData = [
  3.     "username",
  4.     "email",
  5.     "thumbnail_url"
  6.   ]
  7.   
  8.   render() {
  9.     return(<div></div>)
  10.   }
  11. }
复制代码
因此在例子中,在特殊组件请求数据之前,你能使用    App.requiredData快速获取必要的 query 的值。  
  总结:你也许几乎不会使用    static来保存数据。  
  五、其他方式...

  其实是有另一个选择,我没有在标题中说明,因为你不应该这样做:你可以存储在一个全局变量,然后通过一个文件进行导出。
  这是一个特别的场景,然后大多数情况下你不应该这样做。
  1. import React from 'react'
  2. let counter = 0
  3. class App extends React.Component {
  4.   constructor(props) {
  5.     super(props)
  6.     this.addOne = this.addOne.bind(this)
  7.   }
  8.   
  9.   addOne() {
  10.     counter += 1
  11.     this.forceUpdate()
  12.   }
  13.   
  14.   render() {
  15.     return (
  16.       <div>
  17.         <button
  18.           onClick={ this.addOne }>
  19.           Increment
  20.         </button>
  21.         { counter }
  22.       </div>
  23.     )
  24.   }
  25. }
  26. export default App
复制代码
你能够看到和使用    this是类似的,除了使用的是一个全局的变量。  
  如果你需要跨组件的共享数据以及保存一个全局变量,大多数更好的是使用 Redux    store。  
  总结:不要使用全局变量。
  原文出自:    https://medium.freecodecamp.com/where-do-i-belong-a-guide-to-saving-react-component-data-in-state-store-static-and-this-c49b335e2a00#.yvhqqxdkh
友荐云推荐




上一篇:一行代码集成今日头条效果
下一篇:最专业的配送体系 江湖外卖O2O系统一站式解决方案
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

张桐同 发表于 2016-10-17 11:38:53
珍爱生命,张桐同果断回帖。
回复 支持 反对

使用道具 举报

慕梅 发表于 2016-11-7 04:39:03
为何要放弃治疗?
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表