react自定義實現(xiàn)狀態(tài)管理詳解
更新時間:2024年01月15日 14:37:53 作者:不努力code
這篇文章主要為大家詳細介紹了react如何自定義實現(xiàn)狀態(tài)管理,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
redux基礎(chǔ)實現(xiàn)
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
和源碼可能不同,我沒看過源碼,只是實現(xiàn)一下
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自定義實現(xiàn)狀態(tài)管理詳解的詳細內(nèi)容,更多關(guān)于react狀態(tài)管理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React不使用requestIdleCallback實現(xiàn)調(diào)度原理解析
這篇文章主要為大家介紹了React不使用requestIdleCallback實現(xiàn)調(diào)度原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11