react自定義實(shí)現(xiàn)狀態(tài)管理詳解
redux基礎(chǔ)實(shí)現(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
和源碼可能不同,我沒看過源碼,只是實(shí)現(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自定義實(shí)現(xiàn)狀態(tài)管理詳解的詳細(xì)內(nèi)容,更多關(guān)于react狀態(tài)管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
react實(shí)現(xiàn)復(fù)選框全選和反選組件效果
這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)復(fù)選框全選和反選組件效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08React實(shí)現(xiàn)點(diǎn)擊刪除列表中對(duì)應(yīng)項(xiàng)
本文主要介紹了React 點(diǎn)擊刪除列表中對(duì)應(yīng)項(xiàng)的方法。具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01React項(xiàng)目中使用Redux的?react-redux
這篇文章主要介紹了React項(xiàng)目中使用Redux的?react-redux,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09React不使用requestIdleCallback實(shí)現(xiàn)調(diào)度原理解析
這篇文章主要為大家介紹了React不使用requestIdleCallback實(shí)現(xiàn)調(diào)度原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11詳解如何使用React?Redux實(shí)現(xiàn)異步請(qǐng)求
這篇文章主要為大家詳細(xì)介紹了如何使用React?Redux實(shí)現(xiàn)異步請(qǐng)求,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下2025-01-01