react自定义实现状态管理详解
作者:不努力code
这篇文章主要为大家详细介绍了react如何自定义实现状态管理,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
redux基础实现
myRedux
export const createStore = (reduce) => { if (typeof reduce !== 'function') throw new Error('Expected the reducer to be a function.') let state, listeners = [] state = reduce() const getState = () => state const dispatch = (action) => { if(typeof action !== 'object' || typeof action.type !== 'string') throw new Error('Actions must be plain objects.') state = reduce(state, action) listeners.forEach(listener => listener()) } const subscribe = (listener) => { if(typeof listener !== 'function') throw new Error('Expected the listener to be a function.') listeners.push(listener) return () => listeners = listeners.filter(l => l !== listener) } return { getState, dispatch, subscribe, } }
使用
import React, { useEffect, useState } from 'react' import { createStore } from './myRedux' const reduce = (state = { a: 123 }, action = {}) => { state = { ...state } switch (action.type) { case 'tset': state.a = Math.random() * 1000 return state default: return state } } const store = createStore(reduce) export default function Test() { const state = store.getState() const [_, foceUpdate] = useState(0) useEffect(() => { store.subscribe(() => { foceUpdate(Date.now()) }) }, []) const change = () => { store.dispatch({ type: 'tset' }) } return ( <div> <h1>Test {state.a}</h1> <button onClick={change} >change</button> </div> ) }
react-redux
和源码可能不同,我没看过源码,只是实现一下
react-redux.js
import { useContext, useEffect, useState, createContext } from 'react' const StoreContext = createContext() export const Provider = (props) => { const store = props.store return <StoreContext.Provider value={{ store }}>{props.children}</StoreContext.Provider> } export const connect = (mapState, mapDispatch) => { if (typeof mapState !== 'function') throw new Error('mapState must be an function') if (typeof mapDispatch !== 'function') throw new Error('mapDispatch must be an function') return (Cpn) => { return (props = {}) => { const contents = useContext(StoreContext) const store = contents.store const state = mapState(store.getState()) const dispatch = mapDispatch(store.dispatch) const [_, forceUpdate] = useState(true) useEffect(() => { store.subscribe(() => { forceUpdate(Symbol()) }) }, []) props = { ...props, ...state, ...dispatch } return <Cpn {...props} /> } } }
使用
import React from 'react' import { Provider, connect } from './react-redux' import { createStore } from 'redux' const reducer = (state = { name: 'test' }, action) => { switch (action.type) { case 'CHANGE_NAME': return { ...state, name: action.name } default: return state } } const store = createStore(reducer) function Test2(props) { const change = () => { props.changeName('test' + Math.random()) } return ( <div> <h1>Test {props.name} </h1> <button onClick={change} >change</button> </div> ) } const Test3 = connect( state => ({ name: state.name }), dispatch => ({ changeName: (name) => dispatch({ type: "CHANGE_NAME", name }) }) )(Test2) export default function Test() { return ( <Provider store={store} > <Test3 /> </Provider> ) }
模仿pinia方式管理
myPinia.js
export const createStore = (f) => { if (typeof f !== 'function') throw new Error('Expected a function') const state = f() watch(state) const proxy = new Proxy(state, { get: (target, prop) => { const v = target[prop] const isState = v instanceof StoreState return isState ? v.value : v }, set: () => state, }) const userStore = () => { return proxy } return userStore } const watch = (obj) => { Object.keys(obj).forEach((key) => { const storeState = obj[key] if (storeState instanceof StoreState) { let value = storeState.value Object.defineProperty(storeState, 'value', { get: () => value, set: (newValue) => { value = newValue updateView() }, }) } }) } class StoreState { constructor(value) { this.value = value } } export const useStoreState = (value) => { return new StoreState(value) } let listeners = [] const updateView = () => listeners.forEach((f) => f()) export const subscribe = (f) => { if (typeof f !== 'function') throw new Error('Expected a function') if (!listeners.includes(f)) listeners.push(f) return () => (listeners = listeners.filter((l) => l !== f)) }
使用
import React, { useEffect, useState } from 'react' import { createStore, useStoreState, subscribe } from './myPinia' const userStore = createStore(() => { let a = useStoreState(123) const change = () => { a.value++ } return { a, change } }) export default function Test() { const [_, forceUpdate] = useState(0) useEffect(() => { subscribe(() => forceUpdate(Date.now())) }, []) const store = userStore() const change = () => { store.change() console.log(store.a); } return ( <div> <h1>test {store.a}</h1> <button onClick={change} >change</button> </div> ) }
不足的是,还是需要forceUpdate
以上就是react自定义实现状态管理详解的详细内容,更多关于react状态管理的资料请关注脚本之家其它相关文章!