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中間件了,類(lèi)似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簡(jiǎn)單實(shí)現(xiàn)防抖和節(jié)流
在日常開(kāi)發(fā)中,我們經(jīng)常會(huì)有防抖和節(jié)流的需要,可以減小服務(wù)器端壓力,提升用戶(hù)體驗(yàn),本文就詳細(xì)的介紹了react簡(jiǎn)單實(shí)現(xiàn)防抖和節(jié)流,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
React路由跳轉(zhuǎn)的實(shí)現(xiàn)示例
在React中,可以使用多種方法進(jìn)行路由跳轉(zhuǎn),本文主要介紹了React路由跳轉(zhuǎn)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12
用React-Native+Mobx做一個(gè)迷你水果商城APP(附源碼)
這篇文章主要介紹了用React-Native+Mobx做一個(gè)迷你水果商城APP,功能需要的朋友可以參考下2017-12-12
React找不到模塊“./index.module.scss”或其相應(yīng)的類(lèi)型聲明及解決方法
這篇文章主要介紹了React找不到模塊“./index.module.scss”或其相應(yīng)的類(lèi)型聲明及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
react使用antd-design中select不能及時(shí)刷新問(wèn)題及解決
這篇文章主要介紹了react使用antd-design中select不能及時(shí)刷新問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
詳解React Native 采用Fetch方式發(fā)送跨域POST請(qǐng)求
這篇文章主要介紹了詳解React Native 采用Fetch方式發(fā)送跨域POST請(qǐng)求,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
基于React實(shí)現(xiàn)搜索GitHub用戶(hù)功能
在本篇博客中,我們將介紹如何在 React 應(yīng)用中搜索 GitHub 用戶(hù)并顯示他們的信息,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-02-02

