手写React状态管理库 - react-redux篇

98 阅读2分钟

手写react-redux

当我们使用redux的时候,每次都需要在useEffect中订阅和取消订阅,如果想要更像react, (注意redux只是js状态管理库), 我们可以使用react-redux。

export default function ReactReduxPage(){
    const count = useSelector(( { count }) => count);
    const dispatch = useDispatch()
    const add = useCallback(() => {
        dispatch({type: "ADD"})
    },[])
    return (
        <div>
            <h1>ReactReduxPage</h1>
            <button onClick={add}>{count}</button>
        </div>
    )
}
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import {Provider} from '../react-redux-nut/Provider'
import {store} from '../store'

createRoot(document.getElementById('root')).render(
  <Provider store={store}>
    <App />
  </Provider>,
)

我们发现对比redux(具体可以看juejin.cn/post/753167…)。 我们可以发现

  1. 用法变得简单了,我们可以使用useSelector,useDispatch获得store的状态和行为。
  2. 不再需要手动订阅和取消订阅了。
  3. ReactReduxPage并不需要引入store了,store的来源是Provider传下来的。

这是因为react-redux内部帮我们实现了。

接下来,让我们一步一步来看看react-redux具体怎么实现。

  1. Provider实现 既然叫Provider,又出现在了顶部组件中,很容易想到react跨组件传递方法: useContext吧。

要知道,分三步走:

(1)创建Context对象 (2)Provider传递value (3)后代消费value

export const Context = React.createContext()
export function Provider({store,children}){
    return <Context.Provider value={store}>{children}</Context.Provider>
}

  1. useSelector和useDispatch

    想要去实现这些方法,我们得先看用法,知道我接收什么,返回什么。 useSelector接收一个函数,返回一个状态值。 useDispatch就是返回redux中的store.dispatch。 那么我们就可以实现了。这里没有什么难的

export function useSelector(selector){
    const store = useContext(Context)
    const {getState,subscribe} = store
    const selectedState = selector(getState())
    return selectedState
}
export function useDispatch(){
    const store = useContext(Context)
    const {dispatch} = store
    return dispatch
}

好了,现在我们就实现了一个基本的react-redux,但是此时点击按钮,会发现数字没有改变,因为我们还没有订阅嘛,在使用redux和redux-toolkit也会经常用到这个问题,所以一定要记住,订阅!订阅!订阅!

  1. react-redux怎么做订阅呢?

使用useSyncExternalStore API,具体的代码可以参考 https://www.npmjs.com/package/use-sync-external-store

修改一下useSelector

    const store = useContext(Context)
    const {getState,subscribe} = store
    const state = useSyncExternalStore(subscribe,getState)
    const selectedState = selector(state)
    return selectedState

如果只是react18+

import {useSyncExternalStore} from "react"

如果想兼容旧版本

import {useSyncExternalStore} from "use-sync-external-store/shim"

待完成:手写useSyncExternalStore