Redux 毫无疑问是众多 React 项目首选的状态管理方案,但我以为 Redux 的开发体验并很差。javascript
好比当你正在开发一个很复杂的功能,中途须要不断添加全局状态,每次添加都不得不重复以下步骤:css
myFeature
。my-feature/actions.js
、my-feature/reducer.js
、my-feature/type.js
以上只是加个状态而已,写不少模板代码仍是其次,最要命的是会打断你写代码的思路。java
并且随着项目愈来愈大, redux 的状态树也会变大,维护也会变困难。react
useContext
和 useReducer
是 React 16.8 引入的新 API。git
useContext
:可访问全局状态,避免一层层的传递状态。github
useReducer
:用过 Redux 确定不会陌生,它主要用于更新复杂逻辑的状态。redux
下面经过一个简单例子介绍 useContext + useReducer 是如何替代 Redux 的。app
代码已放到 codesandbox,查看完整代码dom
这个例子只有一个功能,点击按钮改变字体颜色。ide
首先用 create-react-app 建立一个项目,也能够在 CodeSandbox 上建立一个 React App。
import React from 'react'
const ShowArea = (props) => {
return (
<div style={{color: "blue"}}>字体颜色展现为blue</div>
)
}
export default ShowArea
复制代码
import React from "react";
const Buttons = props => {
return (
<React.Fragment> <button>红色</button> <button>黄色</button> </React.Fragment> ); }; export default Buttons; 复制代码
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import ShowArea from './ShowArea'
import Buttons from './Buttons'
function App() {
return (
<div className="App"> <ShowArea /> <Button /> </div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement); 复制代码
很明显 ShowArea 组件须要一个颜色状态,因此咱们建立 color.js 来处理状态。
// color.js
import React, { createContext } from "react";
// 建立 context
export const ColorContext = createContext({});
/** * 建立一个 Color 组件 * Color 组件包裹的全部子组件均可以经过调用 ColorContext 访问到 value */
export const Color = props => {
return (
<ColorContext.Provider value={{ color: "blue" }}> {props.children} </ColorContext.Provider> ); }; 复制代码
修改 index.js,让全部子组件均可以访问到颜色。
// index.js
···
···
···
import { Color } from "./color";
function App() {
return (
<div className="App"> <Color> <ShowArea /> <Buttons /> </Color> </div>
);
}
···
···
···
复制代码
在 ShowArea 组件中获取颜色
// ShowArea.js
···
···
···
import { ColorContext } from "./color";
const ShowArea = props => {
const { color } = useContext(ColorContext);
return <div style={{ color: color }}>字体颜色展现为{color}</div>;
};
···
···
···
复制代码
接着在 color.js 中添加 reducer, 用于处理颜色更新的逻辑。
import React, { createContext, useReducer } from "react";
// 建立 context
export const ColorContext = createContext({});
// reducer
export const UPDATE_COLOR = "UPDATE_COLOR"
const reducer = (state, action) => {
switch(action.type) {
case UPDATE_COLOR:
return action.color
default:
return state
}
}
/** * 建立一个 Color 组件 * Color 组件包裹的全部组件均可以访问到 value */
export const Color = props => {
const [color, dispatch] = useReducer(reducer, 'blue')
return (
<ColorContext.Provider value={{color, dispatch}}> {props.children} </ColorContext.Provider> ); }; 复制代码
为按钮添加点击事件,调用 dispatch 就能够更新颜色了。
// buttons.js
import React, { useContext } from "react";
import { colorContext, UPDATE_COLOR } from "./color";
const Buttons = props => {
const { dispatch } = useContext(colorContext);
return (
<React.Fragment> <button onClick={() => { dispatch({ type: UPDATE_COLOR, color: "red" }); }} > 红色 </button> <button onClick={() => { dispatch({ type: UPDATE_COLOR, color: "yellow" }); }} > 黄色 </button> </React.Fragment> ); }; export default Buttons; 复制代码
因此 useContext + useReducer 彻底能够替代 React 进行状态管理。可是目前绝大多数 React 项目仍在使用 Redux,因此深刻学习 Redux 仍是颇有必要的。