react-redux實(shí)現(xiàn)

Redux實(shí)現(xiàn)見(jiàn)如下地址。

http://www.itdecent.cn/p/41499425c475

react-redux可以幫助redux更好的在react中使用
主要提供Provider,useSelector、useDispatch和connect方法

Provider實(shí)現(xiàn)

依賴React的context讓全局可訪問(wèn)store

const context = React.createContext()

function Provider({ store, children }) {
    return <context.Provider value={store}>{children}</context.Provider>
}

useSelector和useDispatch實(shí)現(xiàn)

//一個(gè)強(qiáng)制組件更新的自定義hooks
function useForceUpdate() {
    const [, setState] = useReducer((x) => x + 1, 0);
    const update = useCallback(() => {
        setState()
    }, [])
    return update
}

function useSelector(mapState) {
    const store = useContext(context)
    const update = useForceUpdate()
    //它會(huì)在所有的 DOM 變更之后同步調(diào)用 effect??梢允褂盟鼇?lái)讀取 DOM 布局并同步觸發(fā)重渲染。
    //在瀏覽器執(zhí)行繪制之前,useLayoutEffect 內(nèi)部的更新計(jì)劃將被同步刷新。
    useLayoutEffect(() => {
        const unsubscribe = store.subscribe(() => {
            update()
        })
        return () => {
            unsubscribe()
        }
    }, [store])

    return mapState(store.getState())
}

function useDispatch() {
    const store = useContext(context)
    return store.dispatch
}

connect實(shí)現(xiàn)

function connect(mapState, mapDispatch) {
    // 返回一個(gè)高階組件函數(shù)
    return function (WrappedComponent) {
        //返回組件
        return function (props) {
            const store = useContext(context)
            const stateProps = mapState(store.getState())
            let dispatchProps = { dispatch: store.dispatch }
            // mapDispatch為對(duì)象的格式如下
            // {
            //    parapmsChange: (prams) => ({ type: prams })
            // }
            if (typeof mapDispatch === 'object') {
                let obj = {}
                Object.keys(mapDispatch).forEach(item => {
                    obj[item] = function (parapm) {
                        store.dispatch(mapDispatch[item](parapm))
                    }
                })
                dispatchProps = obj
            } else if (typeof mapDispatch === 'function') {
                dispatchProps = mapDispatch(store.dispatch)
            }
            
            const update = useForceUpdate()
            useLayoutEffect(() => {
                const unsubscribe = store.subscribe(() => {
                    update()
                })
                return () => {
                    unsubscribe()
                }
            }, [store])

            return <WrappedComponent {...props} {...stateProps} {...dispatchProps} />;
        }
    }
}

測(cè)試代碼

import { createStore } from './redux'

const reducer = function (state = { count: 1 }, action) {
    switch (action.type) {
        case 'increase':
            state.count += 1
            return JSON.parse(JSON.stringify(state))
        case 'decrease':
            state.count -= 1
            return JSON.parse(JSON.stringify(state))
        default:
            return JSON.parse(JSON.stringify(state))
    }
}

export default createStore(reducer)
import store from './store/index'
import { Provider } from './react-redux'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
import React from 'react';
import { connect, useDispatch, useSelector } from './react-redux'
class ClassComp extends React.Component {
  render() {
    const { count, parapmsChange } = this.props
    return <div >
      <button onClick={() => parapmsChange('increase')}>parapmsChange+</button>
      ClassComp {count}
      <button onClick={() => parapmsChange('decrease')}>parapmsChange-</button>
    </div>
  }
}

const NewClassComp = connect(state => ({ count: state.count }), 
{ parapmsChange: (prams) => ({ type: prams }) })(ClassComp)

function FnComp() {
  const count = useSelector(state => state.count)
  const dispatch = useDispatch();
  return <div>
    <button onClick={() => dispatch({ type: 'increase' })}>+</button>
    FnComp {count}
    <button onClick={() => dispatch({ type: 'decrease' })}>-</button>
  </div>
}

function App() {
  return (
    <div className="App">
      <NewClassComp />
      <FnComp />
    </div>
  );
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容