useReducer?createContext代替Redux原理示例解析
前言
最近看到很多采用useReducer + createContext
實(shí)現(xiàn)一個(gè)簡(jiǎn)易的redux
的方案,今天親自試了一下,發(fā)現(xiàn)還是會(huì)有一些區(qū)別的。
采用react-redux實(shí)現(xiàn)
這里使用react-redux
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的狀態(tài)管理例子。
App.jsx根組件
import React from 'react'; import { Button } from './Button'; import { createStore } from 'redux'; import { Provider } from 'react-redux'; import A from './a'; export default function ButtonDemo1() { const reducer = (state, action) => { const { name, theme } = state; switch (action.type) { case 'UPDATENAME': return { ...state, name: `${name} + 1`, }; case 'UPDATETHEME': return { ...state, theme: theme === 'dark' ? 'light' : 'dark', }; default: return state; } }; const store = createStore(reducer, { name: 'fx', theme: 'dark', }); return ( <Provider store={store}> <div> <Button /> <A /> </div> </Provider> ); }
A組件用于dispatch
和接收store
。
A.jsx
import React, { useContext } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { reduxContent } from './index1'; export default function A() { const dispatch = useDispatch(); return ( <div onClick={() => dispatch({ type: 'UPDATENAME' })}> {useSelector((state) => state.name)} </div> ); }
效果如圖:
可以看到,Button
組件未使用redux store
,因此正常渲染了一次。
采用react hooks模擬redux實(shí)現(xiàn)
這里采用useReducer
+ createContext
模擬實(shí)現(xiàn)一個(gè)redux
:
App.jsx
import React, { useReducer, createContext } from 'react'; import { Button } from 'concis'; import A from './a'; export const reduxContent = createContext({}); export default function ButtonDemo1() { const reducer = (state, action) => { const { name, theme } = state; switch (action.type) { case 'UPDATENAME': return { ...state, name: `${name} + 1`, }; case 'UPDATETHEME': return { ...state, theme: theme === 'dark' ? 'light' : 'dark', }; default: return state; } }; const [redux, dispatch] = useReducer(reducer, { name: 'fx', theme: 'dark', }); return ( <reduxContent.Provider value={{ redux, dispatch }}> <Button /> <A /> </reduxContent.Provider> ); }
A.jsx
import React, { useContext } from 'react'; import { reduxContent } from './index1'; export default function A() { const { redux, dispatch } = useContext(reduxContent); return ( <div onClick={() => dispatch({ type: 'UPDATENAME' })}> {redux.name} </div> ); }
同樣,子組件也可以對(duì)store
中的狀態(tài)進(jìn)行get
和dispatch
,但是會(huì)出現(xiàn)這樣的問(wèn)題:
可以看到,Button
組件并沒(méi)有使用store
中的內(nèi)容,但是會(huì)隨著A
組件一起跟著重新渲染,原因其實(shí)就是采用這種方式store
是存儲(chǔ)在根組件的,根組件狀態(tài)發(fā)生了變化(useReducer
),子組件跟著一起重新渲染了,因此解決這個(gè)問(wèn)題的思路其實(shí)和解決常規(guī)的子組件沒(méi)變化一起被更新的思路是一樣的。
可以采用 useMemo
限制 + memo
淺比較。
因此只需要在App.jsx
中這樣修改:
const renderButton = React.useMemo(() => { return <Button />; }, []); return ( <reduxContent.Provider value={{ redux, dispatch }}> <div style={{ display: 'flex', flexWrap: 'wrap' }}> {renderButton} <A /> </div> </reduxContent.Provider> ); }
Button.jsx
const Button = (props) => { ...... }) export default React.memo(Button);
異步action
同樣,如果需要異步dispatch
的話,簡(jiǎn)單的場(chǎng)景其實(shí)單純使用異步操作就可以完成,但是在復(fù)雜的場(chǎng)景下很難對(duì)于異步流進(jìn)行管理和維護(hù),這時(shí)就需要借助redux中間件
了,類似redux-thunk
、redux-saga
,而這也是使用hooks
無(wú)法實(shí)現(xiàn)的,無(wú)法處理副作用,攔截action
去更好的reducer
。
總結(jié)
當(dāng)然,并不是說(shuō)采用react hooks
所實(shí)現(xiàn)的狀態(tài)管理方式?jīng)]有好處,這樣可以更加貼合react
原生,采用react
自身所提供的hook,并且可以減少項(xiàng)目中的redux
各種實(shí)例、減少代碼體積,對(duì)于小型項(xiàng)目或是不需要很多全局狀態(tài)的項(xiàng)目,這種方式確實(shí)是不錯(cuò)的選擇。但是redux
仍然是大型項(xiàng)目中最可靠的保障存在。
以上就是useReducer createContext代替Redux原理示例解析的詳細(xì)內(nèi)容,更多關(guān)于useReducer createContext代替Redux的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
react-router-dom入門使用教程(路由的模糊匹配與嚴(yán)格匹配)
這篇文章主要介紹了react-router-dom入門使用教程,主要介紹路由的模糊匹配與嚴(yán)格匹配,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08react?hooks?d3實(shí)現(xiàn)企查查股權(quán)穿透圖結(jié)構(gòu)圖效果詳解
這篇文章主要為大家介紹了react?hooks?d3實(shí)現(xiàn)企查查股權(quán)穿透圖結(jié)構(gòu)圖效果詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01React實(shí)現(xiàn)虛擬滾動(dòng)的三種思路詳解
在??web??開發(fā)的過(guò)程中,或多或少都會(huì)遇到大列表渲染的場(chǎng)景,為了解決大列表造成的渲染壓力,便出現(xiàn)了虛擬滾動(dòng)技術(shù),本文主要介紹虛擬滾動(dòng)的三種思路,希望對(duì)大家有所幫助2024-04-04Zustand介紹與使用 React狀態(tài)管理工具的解決方案
本文主要介紹了Zustand,一種基于React的狀態(tài)管理庫(kù),Zustand以簡(jiǎn)潔易用、靈活性高及最小化原則等特點(diǎn)脫穎而出,旨在提供簡(jiǎn)單而強(qiáng)大的狀態(tài)管理功能2024-10-10完美解決react-codemirror2?編輯器需點(diǎn)擊一下或者延時(shí)才顯示數(shù)據(jù)的問(wèn)題
這篇文章主要介紹了react-codemirror2編輯器需點(diǎn)擊一下或者延時(shí)才顯示數(shù)據(jù)的問(wèn)題,解決方法也很簡(jiǎn)單,需要手動(dòng)引入自動(dòng)刷新的插件,配置一下參數(shù)就可以了,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-08-08React router動(dòng)態(tài)加載組件之適配器模式的應(yīng)用詳解
這篇文章主要介紹了React router動(dòng)態(tài)加載組件之適配器模式的應(yīng)用 ,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09react中value與defaultValue的區(qū)別及說(shuō)明
這篇文章主要介紹了react中value與defaultValue的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05