New Context API + Hooks 实现简单的store管理

282 阅读2分钟

New Context API + Hooks

useContext

React Hooks提供了useContext来访问context,可以在使用 Consumer 的时候不必包裹 Children

import React, { useContext } from 'react';

function Display() {
  const value = useContext(NumberContext);
  return <div>The answer is {value}.</div>;
}
复制代码

useReducer

useReducer是hooks提供的针对复杂场景替代useState管理状态的API,提供了action和reducer的方式来管理组件内状态,它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}
复制代码


文章(link)提供了一种context配合hooks实现全局状态管理的一种思路,相较于纯context,配合hooks的useReducer提供了更为强大的状态管理能力。

import React, {createContext, useContext, useReducer} from 'react';
export const StateContext = createContext();

export const StateProvider = ({reducer, initialState, children}) =>(
  <StateContext.Provider value={useReducer(reducer, initialState)}>
    {children}
  </StateContext.Provider>
);
export const useStateValue = () => useContext(StateContext);
复制代码


首先新建一个StateContext,然后再StateContext的Provider中将context的值设置为useReducer(reducer, initialState),这样当调用action执行reducer后,context的值也将发生变化,似的引用context值得组件更新。由useReducer也保证了只有在数据变化是才会更新组件。
在访问context数据方便也做了一层useStateValue hooks封装,不需要在每个组件里调用useContext。\

demo

codesandbox

import React, { createContext, useContext, useReducer } from "react";
import { render } from "react-dom";
import { produce } from "immer";

const StateContext = createContext();

const StateProvider = ({ reducer, initialState, children }) => (
  <StateContext.Provider value={useReducer(reducer, initialState)}>
    {children}
  </StateContext.Provider>
);
const useStateValue = () => useContext(StateContext);

function App() {
  const initialState = {
    count: 0
  };
  const reducer = (state = initialState, action) =>
    produce(state, draft => {
      switch (action.type) {
        case "increase": {
          draft.count += 1;
          break;
        }
        case "decrease": {
          draft.count += 1;
          break;
        }
        default:
      }
    });
  return (
    <StateProvider initialState={initialState} reducer={reducer}>
      <Count />
    </StateProvider>
  );
}

const Count = () => {
  const [{ count }, dispatch] = useStateValue();

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={() => dispatch({ type: "increase" })}>Increase</button>
      <button onClick={() => dispatch({ type: "decrease" })}>Decrease</button>
    </div>
  );
};

const rootElement = document.getElementById("root");
render(<App />, rootElement);


作者:水星的卫星
链接:juejin.cn/post/684490… 来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。