React HOOK:useReducer
useReducer
1.useReducer用最简单的话来说就是允许我们在函数组件里面像使用redux一样通过reducer和action来管理我们组件状态的变换
语法:
const [state, dispatch] = useReducer(reducer, initialArg, init?) //useReducer和useState类似,都是用来管理组件状态的,只不过和useState的useReducer不一样的是,useReducer返回的dispatch函数是用来触发某些改变state的action而不是直接设置state的值,至于不同的action如何产生新的state的值则在reducer里面定义。 //useReducer接收的三个参数分别是: //reducer: 这是一个函数,它的签名是(currentState, action) => newState,从它的函数签名可以看出它会接收当前的state和当前dispatch的action为参数,然后返回下一个state,也就是说它负责状态转换的工作。 //initialArg:如果调用者没有提供第三个init参数,这个参数代表的是这个reducer的初始状态,如果init参数有被指定的话,initialArg会被作为参数传进init函数来生成初始状态。 //init: 这是一个用来生成初始状态的函数,它的函数签名是(initialArg) => initialState,从它的函数签名可以看出它会接收useReducer的第二个参数initialArg作为参数,并生成一个初始状态initialState
案例:
import React, { useState, useReducer } from 'react' let todoId = 1 const reducer = (currentState, action) => { switch(action.type) { case 'add': return [...currentState, {id: todoId++, text: action.text}] case 'delete': return currentState.filter(({ id }) => action.id !== id) default: throw new Error('Unsupported action type') } } const Todo = ({ id, text, onDelete }) => { return ( <div> {text} <button onClick={() => onDelete(id)} > remove </button> </div> ) } const App = () => { const [todos, dispatch] = useReducer(reducer, []) const [text, setText] = useState('') return ( <> { todos.map(({ id, text }) => { return ( <Todo text={text} key={id} id={id} onDelete={id => { dispatch({ type: 'delete', id }) }} /> ) }) } <input onChange={event => setText(event.target.value)} /> <button onClick={() => { dispatch({ type: 'add', text }) setText('') }} > add todo </button> </> ) } ReactDOM.render(<App />, document.getElementById('root'))
2.useReducer +useContext实现redux
import React from "react" let context1=React.createContext(null) export default context1 import { useRef, useEffect, useCallback, useState, useMemo, useReducer } from 'react' import Mycontext from "./MyContext.jsx" import Mybox2 from "./Mybox2.jsx" function Mybox() { let [state,dispach]=useReducer((state,action)=>{ if(action.type=="msg"){ state.msg= action.value } else if(action.type=="age"){ state.age= action.value } console.log(state) return JSON.parse(JSON.stringify(state)) },{msg:"hello",age:18}) // useReducer+useContext ==>做出redux框架的功能(全局数据共享) //1.给根组件生成一个数据容器(不是用useState生成的,是用useReducer) //2.把这个数据容器(是一个hook容器)传给子代组件使用,使用的技术是useContext return ( <Mycontext.Provider value={[state,dispach]}> <h1>1</h1> <p>{state.msg}</p> <Mybox2></Mybox2> </Mycontext.Provider> ) } export default Mybox import {useReducer,useContext} from 'react' import context1 from "./MyContext.jsx" import MyBox3 from "./MyBox3.jsx" export default function Mybox2() { const [state,dispacth] = useContext(context1) console.log(state); let fn=()=>{ console.log(6666) dispacth({type:"msg",value:"1234567"}) } return ( <div> <h1>2</h1> <p>{state.msg}</p> <button onClick={fn}>修改</button> <MyBox3></MyBox3> </div> ) } import React,{useContext} from 'react' import context2 from "./MyContext.jsx" export default function Mybox3() { let [state,dispacth]=useContext(context2) return ( <div> <h1>3</h1> <p>{state.msg}</p> </div> ) }