欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

useReducer?createContext代替Redux原理示例解析

 更新時間:2022年11月03日 08:33:45   作者:馮心心愛吃肉  
這篇文章主要為大家介紹了useReducer?createContext代替Redux原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

最近看到很多采用useReducer + createContext 實(shí)現(xiàn)一個簡易的redux的方案,今天親自試了一下,發(fā)現(xiàn)還是會有一些區(qū)別的。

采用react-redux實(shí)現(xiàn)

這里使用react-redux 實(shí)現(xià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)一個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>
  );
}

同樣,子組件也可以對store中的狀態(tài)進(jìn)行getdispatch,但是會出現(xiàn)這樣的問題:

可以看到,Button組件并沒有使用store中的內(nèi)容,但是會隨著A組件一起跟著重新渲染,原因其實(shí)就是采用這種方式store是存儲在根組件的,根組件狀態(tài)發(fā)生了變化(useReducer),子組件跟著一起重新渲染了,因此解決這個問題的思路其實(shí)和解決常規(guī)的子組件沒變化一起被更新的思路是一樣的。

可以采用 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的話,簡單的場景其實(shí)單純使用異步操作就可以完成,但是在復(fù)雜的場景下很難對于異步流進(jìn)行管理和維護(hù),這時就需要借助redux中間件了,類似redux-thunk、redux-saga,而這也是使用hooks無法實(shí)現(xiàn)的,無法處理副作用,攔截action去更好的reducer。

總結(jié)

當(dāng)然,并不是說采用react hooks所實(shí)現(xiàn)的狀態(tài)管理方式?jīng)]有好處,這樣可以更加貼合react原生,采用react自身所提供的hook,并且可以減少項(xiàng)目中的redux各種實(shí)例、減少代碼體積,對于小型項(xiàng)目或是不需要很多全局狀態(tài)的項(xiàng)目,這種方式確實(shí)是不錯的選擇。但是redux仍然是大型項(xiàng)目中最可靠的保障存在。

以上就是useReducer createContext代替Redux原理示例解析的詳細(xì)內(nèi)容,更多關(guān)于useReducer createContext代替Redux的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論