useReducer、useContext替代redux方案

先简单复习一下redux工作流程

dispatch.action
previousState,action
newState
state
action
store
reducers
组件

react-hook替换redux方案

要求列表
  • useReducer、useContext函数
  • action:存放修改state的action,此处与redux的思想一致
  • reducer:用来处理不同action,此处我们不提供初始状态的话,默认会去action找。
  • rootReducer:当reducer过多的时候,我们可以拆分reducer,拆分reducer后,使用combinReducers合并处理成一个大单一的对象。
  • 顶级组件:
    1. 组件利用provider提供context给子组件
      2.useReducer定义,引入reducer并提供初始化状态initialstate
  • 子组件:
    1. useContext使用顶级组件提供的context
    2. 如果需要异步请求,使用useEffect
实现逻辑关键代码:
  • cartReducer.js
// 定义一个action type
const CHANGE_CART_AMOUNT = "CHANGE_CART_AMOUNT";
// 初始化状态数据
const initialState ={
  cartList: []
};
// reducer处理action,返回newState
export const cartReducer = (state, action) => {
  switch (action.type) {
    case CHANGE_CART_AMOUNT:
      let cartList = state?state.cart.cartList:[];
      let cartItem = action.payload;
      return {
        cartList: [...cartList, cartItem]
      };

    default:
      {
        return state;
      }
  }
};

当你除了一个cartReducer之外还有很多reducer,这个时候我们需要拆分并统一管理。

  • rootReducer.js
import { cartReducer,initialStates } from './cartReducer';
import combineReducers from './combineReducers';
import { layoutInitialState, layoutReducer } from './layoutReducer';
export const initialState = {
  layout: layoutInitialState,
  cart: initialStates()
};
//拆分reducer后,使用combinReducers合并处理成一个大单一的对象, 
export const rootReducer = combineReducers({
  layout: layoutReducer,
  cart: cartReducer 
});

这里的combineReducer按照redux逻辑,直接写,不是用redux的。
redux的combineReducer工作原理参考:https://www.cnblogs.com/wy1935/p/7109701.html

  • combineReducers.js
//将多个reducer合并成一个reducer
const combineReducers = reducers => {
  return (state = {}, action) => {
    const newState = {};

    for (let key in reducers) {
      newState[key] = reducers[key](state, action);
    }

    return newState;
  }; 
};

export default combineReducers;

  • 顶级组件.jsx
    关键代码
const AppContext = createContext({
  state: initialState,
  dispatch: () => {} 
});
//由于创建的contenxt AppContext需要在各个组件都用uesContext使用到,所以需要导出。
export default AppContext;

 //Redux 是通过 createStore(reducer, initialState) 来创建一个 store 实例,
  // 实例封装了 state 的读写接口和监听接口:getState 、dispatch、subscribe

// 在Redux中,store.dispatch 触发事件动作时,Redux 并不会为我们主动重新渲染视图,而是需要我们调用 store.subscribe 在监听函数中手动 render 视图

//但 useReducer Hook 是没有使用 store 实例,
//而是遵循 Hook 总是返回读写接口的规则,直接通过 [state, dispatch] = useReducer(reducer, initialState) 的方式返回状态的读写接口。

const [state, dispatch] = useReducer(rootReducer,initialState);


//由于布局数据几乎不变化,我们可以使用缓存,等变化再更新,利用dispatch去触发我们上面定义的rootReducer
  const contextValue = useMemo(() => {
    return {
      state,
      dispatch
    };
  }, [state, dispatch]);
  
//Provider传递参数
  return <AppContext.Provider value={contextValue}>
    </AppContext.Provider>;
    

  • 子组件.jsx:在react-hook中,我们只需要触发reducer就能实现像redux-store的dispatch效果一样。
// 触发dispatch
  const {
    state,
    dispatch
  } = useAppContext();
  
  const handleCartAmountChange = useCallback((amount, product) => () => {
    dispatch({
      type: "CHANGE_CART_AMOUNT",
      payload: { ...product,
        qty: amount
      }
    });
  }, []);
  
//获取state

  const {
    state
  } = useAppContext();
  
  useEffect(() => {
    setList(state?state.cart.cartList:[])
  },[state]);  
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一缕微风_Acker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值