前置知识
Flux:是Facebook出品的一个数据流框架
- 规定了数据是单向流动的,自顶而下
- 数据存储在数据仓库中(目前,没学redux,可以认为state就是一个存储数据的仓库)
- action是改变数据的唯一原因(本质上就是一个对象,action有两个属性)
- type:字符串,动作的类型
- payload:任意类型(一般为对象),动作发生后的附加信息
- 例如,如果是添加一个学生,则action可以描述为:{type: “addStudent”, payload: {学生对象的数据}}
- 具体改变数据的是一个函数,该函数叫做 reducer,该函数接收两个参数
- reducer必须是纯函数,不能有副作用!!
- 第一个参数:state,表示当前数据仓库中的数据
- 第二个参数:action,描述了如何去改变数据,以及改变数据的一些附加信息
- 该函数必须有一个返回结果,用于表示数据仓库变化之后的数据
- Flux要求,对象是不可变的,如果返回对象,必须创建新的对象
如果要触发reducer,不可以直接调用,而是应该调用一个辅助函数 dispatch(分发器)
- 该函数仅接受一个参数:action
- 该函数会间接去把 state 传给 reducer 并调用它,以达到改变数据的目的
手动实现一个useReducer
```jsx //useReducer.js import {useState} from ‘react’ /**
- 通用的useReducer函数
- @param {*} reducer reducer函数,标准格式
@param {} initialState 初始状态 / export default function useReducer(reducer, initialState, initFunc) { //不把这个useState放外面,就在内部处理 const [state, setState] = useState(initFunc ? initFunc(initialState) : initialState);
function dispatch(action){ const newState = reducer(state, action); console.log(“日志:state的值:”, state, “->”, newState); setState(newState); }
//把初始state暴露出去 return [state, dispatch]; }
//ReducerTest.js import React from ‘react’; import useReducer from ‘./useReducer’; /*
* 根据当前数据,经过action,生成一个新的数据
*/
function nReducer(state, action){ switch(action.type){ case “increase”: return state+1; case “decrease”: if(state===0){ return 0; } return state-1; default: return state; } }
export default function Reducer() { const [n, dispatch] = useReducer(nReducer, 5, (args)=>{ console.log(“经过处理的初始state值:”); return 1; });
return (
<div>
<button onClick={()=>{
dispatch({type: "decrease"});
}}>-</button>
<span> {n} </span>
<button onClick={()=>{
dispatch({type: "increase"});
}}>+</button>
</div>
)
useReducer 函数/hook
跟上述我们实现的一致
useReducer总共有三个参数
第一个参数是要传进来的reducer,第二个参数是useState的初始状态值(没传第三个参数时)
第三个参数是一个函数,一般用于需要复杂数据计算时:
它会将useReducer的第二个参数作为参数传递进来,并将返回值作为useReducer的初始状态值