前端小誌(轉型中)

一個用來記錄人老會忘記的地方

React context認識

2017年09月09日
context是一個很少被使用的屬性,我想一方面在react的教學頁面不會特別提到這點,另一方面介紹的頁面就先警告一般人不要使用。一開始我也是看到警告就沒有研究了,不過在實際遇到情境與研究了HOC以後,確實是挺有趣的。

Context

react的官方文章中,會告訴你props要傳遞每個component很麻煩,所以有了context這個power api,不過下一秒又跟說不建議使用XD

context的用法也相當簡單,這邊不太細講整體用法,請自己看官方文件

總之,在你的context container加上getChildContext與childContextTypes

class Parent extends Component {
  getChildContext() {
    return {key: "value"};
  }
  render() {
    ...
  }
}

Parent.childContextTypes = {
  key: PropTypes...
};

在你的child加上contextTypes,最後呼叫this.context使用

class Child extends Component {

  render() {
    const { key } = this.context;
    ...
  }
}

Child.childContextTypes = {
  key: PropTypes...
};

為什麼不要使用context的原因

  1. 很難找到source
    這與react的特色完全相抵觸,react強調的是props的傳遞與資料的明確性,你的所有東西會照著flow走。而context打破了這個規則,你必須去翻你的source code。當然現在的IDE都很猛,可能也不是很care,但是跟原生react比,確實有這個問題。

  2. 造成耦合度
    原本的component只要接收props就可以在任何地方,任何專案中使用,但是一但使用了context,你必須綁定某個parent,這樣是增加了耦合度。

  3. 難以test
    如果有在寫test,因為component的data要從context取得而非props,實際想想就覺得很困難。

  4. 語意不清與render問題
    從setState你可以馬上看的懂state要改變了,但是getChildContext是跟著setState一起的,這本身語意上就不清晰,另外因為getChildContext這個method會在props or state改變的時候被呼叫,所以你要改變context的值應該使用props or state(但這其實就是不好的做法)。
    因為child更新context會被shouldCompoentUpdate所擋下來。這邊並不是指child本身shouldCompoentUpdate,而是parent到child之間所有的component若是有實作shouldCompoentUpdate且return false,更大的機率可能用了PureComponent,這樣就會導致child更新失敗。

    所以所以重點來了

    1. context不應該被改變(or shalow immutable)。
    2. 承上,context只應該在constructor的時候收到一次。

    基於以上理由我們可以

    1. 將context由props or state搬到外面轉為Dependency injection。
    2. 加上observe pattern,訂閱Dependency Object,當Object改變時,主動告知底下改變。

    這篇必看!!!

打完這篇我也將專案中的context先拆掉了(因為本來就可以用provider+hoc的方式處理),但是使用provider本身也就有相當的耦合度,主要還是看架構,再來決定你的component要如何設計囉。


展開Disqus
分類
最近文章
友站連結
© 2019 Ernie Yang