前端应用状态管理 —— 状态提高

上一个评论功能的案例中,可能会有些同窗会对一个地方感到疑惑: CommentList 中显示的评论列表数据为何要经过父组件 CommentApp 用 props 传进来?为何不直接存放在 CommentList 的 state 当中?例如这样作也是能够的:html

class CommentList extends Component {
  constructor () {
    this.state = { comments: [] }
  }

  addComment (comment) {
    this.state.comments.push(comment)
    this.setState({
      comments: this.state.comments
    })
  }

  render() {
    return (
      <div>
        {this.state.comments.map((comment, i) =>
          <Comment comment={comment} key={i} />
        )}
      </div>
    )
  }
}

若是把这个 comments 放到 CommentList 当中,当有别的组件也依赖这个 comments数据或者有别的组件会影响这个数据,那么就带来问题了。举一个数据依赖的例子:例如,如今咱们有另一个和 CommentList 同级的 CommentList2 ,也是须要显示一样的评论列表数据。函数

CommentList2 和 CommentList 并列为 CommentApp 的子组件,它也须要依赖 comments 显示评论列表。可是由于 comments 数据在 CommentList 中,它没办法访问到。工具

遇到这种状况,咱们将这种组件之间共享的状态交给组件最近的公共父节点保管,而后经过 props 把状态传递给子组件,这样就能够在组件之间共享数据了。this

在咱们的例子当中,若是把 comments 交给父组件 CommentApp ,那么 CommentList和 CommentList2 均可以经过 props 获取到 comments,React.js 把这种行为叫作“状态提高”。spa

可是这个 CommentList2 是咱们临时加上去的,在实际案例当中并无涉及到这种组件之间依赖 comments 的状况,为何还须要把 comments 提高到 CommentApp?那是由于有个组件会影响到 comments ,那就是 CommentInputCommentInput 产生的新的评论数据是会插入 comments 当中的,因此咱们遇到这种状况也会把状态提高到父组件。code

总结一下:当某个状态被多个组件依赖或者影响的时候,就把该状态提高到这些组件的最近公共父组件中去管理,用 props 传递数据或者函数来管理这种依赖或着影响的行为。htm

咱们来看看状态提高更多的例子,假设如今咱们的父组件 CommentApp 只是属于更大的组件树 PostApp 的一部分:blog

而这个更大的组件树的另外的子树的 CommentsCount 组件也须要依赖 comments 来显示评论数,那咱们就只能把 comments 继续提高到这些依赖组件的最近公共父组件 PostApp 当中。生命周期

如今继续让咱们的例子极端起来。假设如今 PostApp 只是另一个更大的父组件 Index 的子树。而 Index 的某个子树的有一个按钮组件能够一键清空全部 comments(也就是说,这个按钮组件能够影响到这个数据),咱们只能继续 commenets 提高到 Index 当中。get

你会发现这种无限制的提高不是一个好的解决方案。一旦发生了提高,你就须要修改原来保存这个状态的组件的代码,也要把整个数据传递路径通过的组件都修改一遍,好让数据可以一层层地传递下去。这样对代码的组织管理维护带来很大的问题。到这里你能够抽象一下问题:

如何更好的管理这种被多个组件所依赖或影响的状态?

你能够看到 React.js 并无提供好的解决方案来管理这种组件之间的共享状态。在实际项目当中状态提高并非一个好的解决方案,因此咱们后续会引入 Redux 这样的状态管理工具来帮助咱们来管理这种共享状态,可是在讲解到 Redux 以前,咱们暂时采起状态提高的方式来进行管理。

对于不会被多个组件依赖和影响的状态(例如某种下拉菜单的展开和收起状态),通常来讲只须要保存在组件内部便可,不须要作提高或者特殊的管理。

相关文章
相关标签/搜索