Reducer Hook
Flux:Facebook出品的一个数据流框架
- 规定了数据是单向流动的
- 数据存储在数据仓库中(目前,可认为state就是一个存储数据的仓库)
- action是改变数据的唯一原因(本质上就是一个对象,action有两个属性)
- type:字符串,动作的类型
- payload:任意类型,动作发生后的附加信息
- 具体改变数据的是个函数,该函数叫做reducer
- 该函数接收两个参数
- state:表示当前数据仓库中的数据
- action:描述了如何去改变数据,以及改变数据的一些附加信息
- 该函数必须有一个返回结果,用于表示数据仓库变化之后的数据
- Flux要求,对象是不可变的。如果返回对象,必须创建新的对象
- 该函数接收两个参数
- 如果要触发reducer,不可直接调用,而是应该调用一个辅助函数dispatch
- 该函数仅接受一个参数:action
- 该函数会间接去调用reducer,以达到改变数据的目的
自己手写这个数据流:
import React, { useState } from 'react'
function reducer(state, action) {
switch (action.type) {
case 'increase':
return state + 1
case 'decrease':
return state - 1
default:
return state
}
}
export default function HookCounter() {
const [count, setCount] = useState(0)
function dispatch(action) {
const newCount = reducer(count, action)
console.log(`日志:n的值 ${count} => ${newCount}`)
setCount(newCount)
}
return (
<div>
<button onClick={() => dispatch({type: 'increase'})}>+</button>
<span>{count}</span>
<button onClick={() => dispatch({type: 'decrease'})}>-</button>
</div>
)
}
使用自定义Hook优化:
import React, { useState } from 'react'
function reducer(state, action) {
switch (action.type) {
case 'increase':
return state + 1
case 'decrease':
return state - 1
default:
return state
}
}
function useMyReducer() {
const [count, setCount] = useState(0)
function dispatch(action) {
const newCount = reducer(count, action)
console.log(`日志:n的值 ${count} => ${newCount}`)
setCount(newCount)
}
return [count, dispatch]
}
export default function HookCounter() {
const [count, dispatch] = useMyReducer()
return (
<div>
<button onClick={() => dispatch({type: 'increase'})}>+</button>
<span>{count}</span>
<button onClick={() => dispatch({type: 'decrease'})}>-</button>
</div>
)
}
通用化自定义reducer:
import React, { useState } from 'react'
function reducer(state, action) {
switch (action.type) {
case 'increase':
return state + 1
case 'decrease':
return state - 1
default:
return state
}
}
/**
* 通用的useMyReducer函数
* @param {function} reducer reducer函数,标准格式的
* @param {any} initialState 初始状态
*/
function useMyReducer(reducer, initialState) {
const [state, setState] = useState(initialState)
function dispatch(action) {
const newState = reducer(state, action)
console.log(`日志: ${state} => ${newState}`)
setState(newState)
}
return [state, dispatch]
}
export default function HookCounter() {
const [count, dispatch] = useMyReducer(reducer, 0)
return (
<div>
<button onClick={() => dispatch({type: 'increase'})}>+</button>
<span>{count}</span>
<button onClick={() => dispatch({type: 'decrease'})}>-</button>
</div>
)
}
使用Reducer Hook
import React, { useState, useReducer } from 'react'
function reducer(state, action) {
switch (action.type) {
case 'increase':
return state + 1
case 'decrease':
return state - 1
default:
return state
}
}
export default function HookCounter() {
// useReducer 第三个参数是可选的函数 函数返回数用来替代第二个参数(初始状态)
const [count, dispatch] = useReducer(reducer, 7, (secondParam) => {
// 传过来的参数是 第二个参数 -> 7
console.log(secondParam)
// 现在初始值不是7 而是100了
return 100
})
// 第三个参数通常没啥用 它的本意是通过对第二个参数进行一大堆运算 再重新得到一个初始值
return (
<div>
<button onClick={() => dispatch({type: 'increase'})}>+</button>
<span>{count}</span>
<button onClick={() => dispatch({type: 'decrease'})}>-</button>
</div>
)
}
网友评论