react-redux实现

Redux实现见如下地址。

https://www.jianshu.com/p/41499425c475

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

Provider实现

依赖React的context让全局可访问store

const context = React.createContext()

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

useSelector和useDispatch实现

//一个强制组件更新的自定义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()
    //它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。
    //在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。
    useLayoutEffect(() => {
        const unsubscribe = store.subscribe(() => {
            update()
        })
        return () => {
            unsubscribe()
        }
    }, [store])

    return mapState(store.getState())
}

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

connect实现

function connect(mapState, mapDispatch) {
    // 返回一个高阶组件函数
    return function (WrappedComponent) {
        //返回组件
        return function (props) {
            const store = useContext(context)
            const stateProps = mapState(store.getState())
            let dispatchProps = { dispatch: store.dispatch }
            // mapDispatch为对象的格式如下
            // {
            //    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} />;
        }
    }
}

测试代码

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>
  );
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容