react的class类组件中,使用Reducer可以进行全局的状态管理,但是Reducer文件本身过于臃肿,逻辑解构比较复杂,学习的难度较大,于是可以通过使用函数组件的hooks来实现比较简单的状态管理。
在react函数组件中,使用hooks语法可以轻松实现许多功能,但其有一个缺陷便是hooks不具备直接进行状态管理的能力,因此要想在hooks中进行状态管理,就必须借助一些重要的API,比如createContext、useContext、useReducer等。下面介绍hooks全局状态管理的实现过程:
案例:制作一个组件Demo,包含子组件Color,Color中又包含子组件ShowText和Buttons。要求实现功能:通过点击组件Buttons内部的按钮,改变组件ShowText内的文本的颜色。
一、逻辑关系图解
通过下图可展示这些组件之间的逻辑关系:
(1)在控制文本颜色信息的组件Color中包含了ShowText和Buttons两个组件,其中组件ShowText负责展示文本的颜色变化情况,组件Buttons负责控制改变ShowText的文本颜色。
(2)在父组件Color中共享出去了两个东西:color和reducerhan'shu,在子组件ShowText中订阅color,在子组件Buttons中订阅reducer函数。
(3)通过调用Buttons组件中订阅的reducer函数传入必要的参数,即可更新color的状态,组件ShowText的文本颜色也会随之发生改变。
二、编码实现
Demo7组件
import React from "react"
import Buttons from "./Buttons.js"
import ShowText from "./ShowText.js"
import {Color} from "./Colors.js"
function Demo7(){
return(
<div>
<Color>
{/*父组件在调用Color组件的时候,传的参数是两个组件
:ShowText和Buttons,而且没有给props定义属性
直接在子组件里面写的,所以子组件拿到参数
就直接用props.childern就行了*/}
<ShowText></ShowText>
<Buttons></Buttons>
</Color>
</div>
)
}
export default Demo7
父组件Demo7在调用子组件Color的时候,传了两个参数:组件ShowText和组件Buttons,所以在子组件Color中应以props.children进行参数的接收
Color组件:
// 引入依赖
import {createContext,useReducer} from "react"
// 创建并导出react上下文:此处是以对象的形式创建导出
export const ColorContext = createContext({})
// 创建,导出action.type意愿
export ChangeColor = "ChangeColor "
// 创建、导出组件Color
export function Color(props){
console.log(props)
const [color,dispatch] = useReducer((state,action)=>{
switch(action.type){
case "ChangeColor":
return action.color
default:
return state
}
},"blue")
// 对外提供,子组件订阅
return(
<div>
{/*向子组件传递的上线文是对象:{color:"blue"}*/}
<ColorContext.Provider value={{color,dispatch}}>
{props.children} {/*这是子组件*/}
</ColorContext.Provider>
</div>
)
}
组件Color通过createContext提供的Provide方法,向外暴露了color和dispatch这两个上下文信息,其子组件需使用useContext方法进行信息的订阅和获取
Buttons组件:
import React,{useContext} from "react"
// 该组件是按钮组件用于改变颜色
import {ChangeColor} from "./Colors.js"
import {ColorContext} from "./Colors.js"
function Buttons(){
console.log(ChangeColor)
const DISPATCH = useContext(ColorContext)
console.log(DISPATCH)
// 然后在button里面调用DISPATCH上下文中的dispatch方法
return(
<div>
<button onClick={()=>{
DISPATCH.dispatch({
type:"ChangeColor",
color:"red",
})
}}>红色</button>
<button onClick={()=>{
DISPATCH.dispatch({
type:"ChangeColor",
color:"purple",
})
}}>紫色</button>
</div>
)
}
export default Buttons
ShowText组件
import React,{useContext} from "react"
// 该组件用户展示文本的初始颜色
import {ColorContext} from "./Colors.js"
function ShowText(){
// 订阅颜色
const {color} = useContext(ColorContext)
console.log(color)
return(
/**
* 这里Color父组件调用子组件ShowText,获取到的颜色是另一个子组件Buttons通过传入参数:action{type:,color:}
来调用父组件组件Color中createContext的Provide提供的dipatch函数来修改更新后得到的新的颜色
*/
<div style={{color:{color}.color}}>
<h2>自己初始的颜色:蓝色</h2>
</div>
)
}
export default ShowText
通过点击Buttons组件中的按钮,调用reducer函数,传入颜色参数,就可以修改全局的color状态了,同时组件ShowText上的文本颜色也会变成与之对应的颜色,实现reducer状态管理的功能。