useReducer + useContext 实现 Redux
useContext:可以访问全局状态,避免一层层的传递状态,这符合 Redux 的一项规则,就是状态全局化,并能统一管理。
useReducer:通过 action 的传递,更新复杂逻辑的状态,主要是可以实现类似 Redux 中的 Reducer 部分,实现业务逻辑的可行性。
第一步,使用 useContext 实现状态共享
①编写UI 组件
showArea.js (整个显示区域)
import React from 'react' import Text from './showText' import Button from './buttons' function showArea(){ return ( <div> <Text/> <Button/> </div> ) } export default showArea;
showText.js 中 的 Text 组件
import React from 'react' function Text() { return ( <h3 style={{ color: 'blue' }}>字体颜色是blue</h3> ) } export default Text;
buttons.js 中的 Button 组件
import React from 'react' function Button() { return ( <div> <button>红色</button> <button>绿色</button> </div> ) } export default Button;
② 利用userContext 编写颜色共享组件 color.js
//颜色共享组件 color.js import React , {createContext} from 'react' export const ColorContext = createContext({}) function Color(props){ return ( <ColorContext.Provider value={{color:"red"}}> {props.children} </ColorContext.Provider> ) } export default Color;
引入了 createContext 用来创建上下文 ColorContext 组件,然后我们要用 { props.children } 来显示对应的子组件(Text 和 Button 组件)
改写 ShowArea 组件,让它可以共享状态,Text 和 Button 组件 共享 Color 组件的状态
import React from 'react' import Text from './showText' import Button from './buttons' import Color from './color' function ShowArea(){ return ( <div> <Color> <Text /> <Button /> </Color> </div> ) } export default ShowArea;
改写 Text 组件,引入 useContext 和 在 color.js 中声明的 ColorContext ,让组件可以接受全局变量 color
import React ,{useContext} from 'react' import {ColorContext} from './color' function Text() { const {color} = useContext(ColorContext) return ( <h3 style={{ color: color}}>字体颜色是{color}</h3> ) } export default Text;
这就通过 useContext 实现了状态的共享
第二步,使用 useReducer 控制业务逻辑
颜色管理的代码都放在了 color.js 中共,所以在文件里添加一个 reducer,用于处理颜色更新的逻辑。先声明一个 reducer 的函数,它就是 javascript 中的普通函数。有了 reducer后,在 color 组件里使用 useReducer ,这样Color 组件就有了那个共享状态和处理业务逻辑的能力,跟以前使用的 redux 几乎一样了。
import React , {createContext,useReducer} from 'react' export const ColorContext = createContext({}) export const COLORCHANGE = 'COLORCHANGE' const reducer=(state,action)=>{ switch(action.type){ case COLORCHANGE: return action.color default: return state } } function Color(props){ const [color,dispatch] = useReducer(reducer,'green') return ( <ColorContext.Provider value={{color,dispatch}}> {/*color和dispatch都共享出去*/} {props.children} </ColorContext.Provider> ) } export default Color;
通过 dispatch 修改状态:
在 Button 组件中使用 dispatch 完成按钮的相应操作。先引入 useContext,ColorContext 和 COLORCHANGE ,然后写 onClick 事件就可以了
import React , {useContext} from 'react' import {ColorContext,COLORCHANGE} from './color' function Button() { const {dispatch} = useContext(ColorContext) //dispatch 是在ColorContext组件中共享出去的 return ( <div> <button onClick={()=>dispatch({type:COLORCHANGE,color:'red'})}>红色</button> <button onClick={()=>dispatch({type:COLORCHANGE,color:'green'})}>绿色</button> </div> ) } export default Button;