前端應用狀態管理 —— 狀態提高

上一個評論功能的案例中,可能會有些同窗會對一個地方感到疑惑: 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 以前,咱們暫時採起狀態提高的方式來進行管理。

對於不會被多個組件依賴和影響的狀態(例如某種下拉菜單的展開和收起狀態),通常來講只須要保存在組件內部便可,不須要作提高或者特殊的管理。

相關文章
相關標籤/搜索