早期的方法,雖然麻煩但也有一些好處。
簡述
用 react redux 串接 redux 的方法有兩種:
目前都會推薦用 hook 的方式來串,但建議還是能了解一下 connect 的做法是怎麼做的。
正文
它背後的原理其實就是「把 store 的東西當作 props 傳到 component 裡面」,我框起來的地方是重點,一定要看懂。
這種作法稱為:
HOC Higher Order Component,意思就是 Component 在包一層 Component
總而言之寫起來會長這樣(先看個大概就好,看不懂沒關係):
1 | import TodoInput from "../components/TodoInput"; |
在解釋這段 code 以前先打個岔。
還記得剛剛說的嗎? connect 的原理只是多包一層 Component 而已,所以關於 Component 其實還可以分成下面這兩個東西:
dump / presentational Component
smart / container Component
那個負責接收 props 的 Component 就叫做 dump component,因為它完全不知道 redux 的存在,它只知道「哦,我會接收到 props,我用就對了」。
而那個負責把 store 傳下去的 Component 就是 smart component,因為它知道 redux 的存在,不像 dump component 純粹只管理 UI 的顯示。
所以這時候呢,資料夾的結構通常會長成這樣子:
- containers
- todoInput.js(dump Component)
- components
- todoInput.js(smart Component)
雖然只看名字的話感覺是一樣的東西,但它背後卻有著 dump 跟 smart 的區別。
這個想法是 Redux 的作者 Dan Abramov 提出的,有興趣的話推薦去看這篇文章:Presentational and Container Components
好,讓我們回來解釋 code 的部分吧。
首先 connect
只是個用來跟 store 串接起來的函式,它會接收兩個參數(function):
1. mapStateToProps
1 | const mapStateToProps = store => { |
跟 useSelector
是差不多的概念,就是「從 store 把想要的 state 選出來」,然後 return,它就會被當成 Props 傳入(它的函式命名我覺得有夠貼切)。
2. mapDispatchToProps
1 | const mapDispatchToProps = dispatch => { |
我是這樣理解啦,你可以先思考這個問題,「現在沒有 useDispatch
能用了,那原本的 Component 要怎麼 dispatch 一個 action?」
剛剛不是有說可以傳 props 嗎?所以只要先在外面這一層把 dispatch 寫好後在當作 props 傳進去就好啦,這就是這一段在做的事情。
順道一提,這邊如果 props 跟 dispatch 的 action 同名,可以用這樣來縮寫:
1 | const mapDispatchToProps = { |
做好以後,最後一步就是把 container/ 底下的 Component 引入使用而已。因為 code 有點多我就不貼這邊了,想看完整的原始碼到這邊來看。
最後只是想提一下,這樣子的做法有什麼好處嗎?
有哦!好處是「測試」比較好測,因為把 Component 都拆成更小的單位了,而且每個 Component 的職責更加分明(負責 UI / 負責 Redux),所以會要測試的項目會單純許多。