react自定義實現(xiàn)狀態(tài)管理詳解
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)管理詳解的詳細(xì)內(nèi)容,更多關(guān)于react狀態(tài)管理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React 的 getDefaultProps簡介、用法與最佳實踐方案
React組件通過getDefaultProps設(shè)置默認(rèn)屬性,防止未傳props導(dǎo)致的錯誤,隨著React發(fā)展,方式從方法演變?yōu)閟tatic defaultProps及函數(shù)參數(shù)默認(rèn)值,建議根據(jù)項目選擇合適語法,本文給大家介紹React 的 getDefaultProps簡介、用法與最佳實踐方案,感興趣的朋友跟隨小編一起看看吧2025-09-09
React Native中ScrollView組件輪播圖與ListView渲染列表組件用法實例分析
這篇文章主要介紹了React Native中ScrollView組件輪播圖與ListView渲染列表組件用法,結(jié)合實例形式詳細(xì)分析了ScrollView組件輪播圖與ListView渲染列表組件具體功能、使用方法與操作注意事項,需要的朋友可以參考下2020-01-01
react組件中的constructor和super知識點整理
這篇文章主要介紹了react組件中的constructor和super知識點整理,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08
React項目中實現(xiàn)數(shù)據(jù)持久化的方法大全
在React應(yīng)用開發(fā)中,數(shù)據(jù)持久化是一個至關(guān)重要的需求,當(dāng)用戶刷新頁面、關(guān)閉瀏覽器后重新打開應(yīng)用,或者在不同設(shè)備間切換時,我們希望能夠保持用戶的數(shù)據(jù)狀態(tài),本文將全面介紹React項目中實現(xiàn)數(shù)據(jù)持久化的各種方法,需要的朋友可以參考下2025-09-09
react如何使用useRef模仿抖音標(biāo)題里面添加標(biāo)簽內(nèi)容
本文介紹了如何模仿抖音發(fā)布頁面,使用div元素作為輸入框,并利用CSS樣式和JavaScript動態(tài)操作DOM,實現(xiàn)類似于input輸入框的功能,感興趣的朋友跟隨小編一起看看吧2024-10-10
react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁的方法
本篇文章主要介紹了react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12

