Hello, 各位勇敢的小夥伴, 你們好, 我是大家的嘴強王者小五, 身體健康, 腦子沒病.
本人有豐富的脫髮技巧, 能讓你一躍成爲資深大咖.react
一看就會一寫就廢是本人的主旨, 菜到摳腳是本人的特色, 卑微中透着一絲絲剛強, 傻人有傻福是對我最大的安慰.web
歡迎來到
小五
的隨筆系列
之Redux在React Hook中的使用及其原理
.redux
下面將從what
, why
, how to
三個方面來講說Reduxsegmentfault
將一個web
應用拆分紅視圖層與數據層, Redux
就是保存其數據的一個容器, 其本質就是維護一個存儲數據的對象.app
const initState = { count: 0, }
Action : 一個 want to do 的過程 (計劃要作一個什麼樣的操做)ide
ActionType
是對Action
的描述, 也是鏈接Action
和Reducer
的橋樑ActionType
和payload
(數據)組成的對象export const increaseConstant = 'INCREASE' // ActionType { type: increaseConstant, payload, } // Action
case increaseConstant: // 當 ActionType 爲 'INCREASE' 時, 執行count++ return { ...state, count: payload + 1 }
當你不知道是否須要使用Redux
的時候, 那就是不須要使用.函數
下面一組動圖很好的描述了一個應用程序的開發過程, 及什麼時候須要Redux
.
圖片來源及原文連接post
Redux
的用武之地了, 使用Redux
後流程以下
在說使用方法以前, 咱們先來從頭至尾模擬一個Redux
的過程, 只要理解原理, 使用起來那不是小菜一碟.spa
Let's go, come on baby!code
下面咱們就用一個簡單的計數器的例子來模擬實現一個Redux的過程:
import React, { useState } from 'react' const CountItem = (props) => { const { count, increase, } = props return ( <> {count} <button onClick={increase}>Count++</button> </> ) } const Count = () => { const [count, setCount] = useState(0) const increase = () => { setCount(count + 1) } return ( <CountItem count={count} increase={increase} /> ) } export default Count
這樣一個簡單的count組件就建立好了, 如今, 咱們想把對數據的操做單獨封裝成一個方法名爲dispatch
, 傳遞的參數爲一個Action
格式: { type: xxx, payload: xxx }
const dispatch = (action) => { switch(action.type) { case 'INCREASE': return action.payload + 1 default: break } }
const increase = () => { - setCount(count + 1) + setCount(dispatch({type: 'INCREASE', payload: count})) }
這時, 咱們將action
對象也抽離出來, 方便複用, 新建action.js
.
const increaseCount = (payload) => { return { type: 'INCREASE', payload } }
const increase = () => { - setCount(dispatch({type: 'INCREASE', payload: count})) + setCount(dispatch(increaseCount(count))) }
接下來咱們把dispatch
中的事件操做抽離到reducer
中, 新建reducer.js
.
const reducer = (state, action) => { const { type, payload } = action switch(type) { case 'INCREASE': return { ...state, count: payload + 1 } default: return state } }
const dispatch = (action) => { const state = { count, } const newState = reducer(state, action) return newState }
const increase = () => { - setCount(dispatch(increaseCount(count))) + setCount(dispatch(increaseCount(count)).count) }
接下來, 咱們把set
方法也拿到dispatch
中, 讓全部操做都在dispatch
中完成.
const dispatch = (action) => { const state = { count, } + const setter = { + count: setCount + } const newState = reducer(state, action) + for (let key in newState) { + setter[key](newState[key]) + } - return newState }
const increase = () => { - setCount(dispatch(increaseCount(count)).count) + dispatch(increaseCount(count)) }
這裏咱們能夠看到, action.type
是鏈接action
和reducer
的橋樑, 咱們能夠將actionType
定義爲常量單獨保存.
export const increaseConstant = 'INCREASE' // 替換 action 和 reducer 中的 'INCREASE' 爲 increaseConstant
基於現有場景, 若是咱們有另外一個功能, 而目前的reducer並不能幫助咱們很好的把不一樣的功能劃分開來, 咱們改造一下reducer
, 改形成一個對象, 用對象的key
去區分功能.
const reducer = { count(state, action) { const { type, payload } = action switch(type) { case increaseConstant: return payload + 1 default: break } }, }
這時咱們要遍歷reducer
, 找到正確的key
, 才能讓程序正確執行, 咱們新建combineReducers.js
來完成這步操做.
const combineReducers = (reducer) => { return (state, action) => { let ret = {} for (let key in reducer) { ret[key] = reducer[key](state[key], action) } return { ...state, ...ret, } } }
繼續改下dispatch
函數, 使其支持當前格式reducer
.
- const newState = reducer(state, action) + const newState = combineReducers(reducer)(state, action)
至此, 一個redux
的實現過程就完成了, 接下來, 咱們實際用一用redux
. 其實, 當完成上述操做的時候, 怎麼用就已經說的差很少了.
action
, reducer
, Count
組件同上, Count組件須要簡單改寫下.
新建store.js
import { createStore, combineReducers } from 'redux' import reducer from './recuder' const initState = { count: 0, } const store = createStore( combineReducers(reducer), initState, ) export default store
新建app.jsx
, 引入store
import { Provider } from 'react-redux' import store from './store' const App = () => { return ( <Provider store={store}> <Count /> </Provider> ) } export default App
改寫Count
組件
import React from 'react' import { connect } from 'react-redux' import { increaseCount } from './action' const CountItem = (props) => { const { count, increase, } = props return ( <> {count} <button onClick={increase}>Count++</button> </> ) } const Count = (props) => { const { count, dispatch, } = props const increase = () => { dispatch(increaseCount(count)) } return <CountItem count={count} increase={increase} /> } export default connect( (state) => { return state }, (dispatch) => { return { dispatch } } )(Count)
接下來, 咱們改寫成hook
的寫法
改寫Count
組件
import React from 'react' - import { connect } from 'react-redux' + import { useSelector, useDispatch } from 'react-redux' import { increaseCount } from './action' const CountItem = (props) => { const { count, increase, } = props return ( <> {count} <button onClick={increase}>Count++</button> </> ) } const Count = () => { - const { - count, - dispatch, - } = props + const count = useSelector(state => state.count) + const dispatch = useDispatch() const increase = () => { dispatch(increaseCount(count)) } return <CountItem count={count} increase={increase} /> } - export default connect( - (state) => { - return state - }, - (dispatch) => { - return { dispatch } - } - )(Count) + export default Count
至此, 本篇文章就到此結束了, 你們能夠寫個複雜一點的組件練習下, 好比todoList, 手動滑稽. 逃了逃了, 我要去timi去了, 個人小夥伴還等我帶他上白銀呢, 一幫混子, 帶不動.