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
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…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。