Reducer Hook

2020-05-24  本文已影响0人  percykuang

Reducer Hook

Flux:Facebook出品的一个数据流框架

  1. 规定了数据是单向流动的
  2. 数据存储在数据仓库中(目前,可认为state就是一个存储数据的仓库)
  3. action是改变数据的唯一原因(本质上就是一个对象,action有两个属性)
    1. type:字符串,动作的类型
    2. payload:任意类型,动作发生后的附加信息
  4. 具体改变数据的是个函数,该函数叫做reducer
    1. 该函数接收两个参数
      1. state:表示当前数据仓库中的数据
      2. action:描述了如何去改变数据,以及改变数据的一些附加信息
    2. 该函数必须有一个返回结果,用于表示数据仓库变化之后的数据
      1. Flux要求,对象是不可变的。如果返回对象,必须创建新的对象
  5. 如果要触发reducer,不可直接调用,而是应该调用一个辅助函数dispatch
    1. 该函数仅接受一个参数:action
    2. 该函数会间接去调用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>
  )
}
上一篇 下一篇

猜你喜欢

热点阅读