useReducer :接受类型为 (state, action) => newState 的reducer,并返回与 dispatch 方法配对的当前状态。(如果你熟悉Redux,你已经知道它是如何工作的。)
下面定义两个计数器Counter组件
和 CounterTest组件
,使用 useReducer 使它们共享一个count state
,当一个组件的 count state发生变化时,另一个组件的count state也会相应的改变。
- reducer.js
import { useReducer } from "react";
const initialState = 0;
function reducer(state, action) {
switch (action.type) {
case "reset":
return initialState;
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
// A reducer must always return a valid state.
// Alternatively you can throw an error if an invalid action is dispatched.
return state;
}
}
export default reducer;
- Counter.js
import React from "react";
function Counter(props) {
return (
<div>
Count: {props.state.count}
<button onClick={() => props.dispatch({ type: "reset" })}>Reset</button>
<button onClick={() => props.dispatch({ type: "increment" })}>+</button>
<button onClick={() => props.dispatch({ type: "decrement" })}>-</button>
</div>
);
}
export default Counter;
- CounterTest.js
import React from "react";
function CounterTest(props) {
return (
<div>
Count: {props.state.count}
<button onClick={() => props.dispatch({ type: "reset" })}>Reset</button>
<button onClick={() => props.dispatch({ type: "increment" })}>+</button>
<button onClick={() => props.dispatch({ type: "decrement" })}>-</button>
</div>
);
}
export default CounterTest;
- index.js
import React, { useReducer } from "react";
import reducer from "./reducer";
import Counter from "./Counter";
import CounterTest from "./CounterTest";
const App = () => {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div className="App">
<Counter state={state} dispatch={dispatch} />
<CounterTest state={state} dispatch={dispatch} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
ps:此处还有两种方法对代码进行优化:
方法一:将共同的状态 state 和 dispatch 通过React.createContext
存入到context中,再通过useContext API
获取context中的内容。
方法二:直接采用React Context API
。
接下来会对这两种方法分别进行说明。