HTML5教程

Redux在React Hook中的使用及其原理

本文主要是介绍Redux在React Hook中的使用及其原理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Hello, 各位勇敢的小伙伴, 大家好, 我是你们的嘴强王者小五, 身体健康, 脑子没病.
 

本人有丰富的脱发技巧, 能让你一跃成为资深大咖.

一看就会一写就废是本人的主旨, 菜到抠脚是本人的特点, 卑微中透着一丝丝刚强, 傻人有傻福是对我最大的安慰.

欢迎来到小五随笔系列Redux在React Hook中的使用及其原理.

浅谈Redux

下面将从what, why, how to 三个方面来说说Redux

第一问 what 什么是Redux

将一个web应用拆分成视图层与数据层, Redux就是保存其数据的一个容器, 其本质就是维护一个存储数据的对象.

  • State : 一个存放数据的容器 (一个对象)
const initState = {
  count: 0,
}
  • Action : 一个 want to do 的过程 (计划要做一个什么样的操作)

    • ActionType是对Action的描述, 也是连接ActionReducer的桥梁
    • 本质上是一个由ActionTypepayload(数据)组成的对象
export const increaseConstant = 'INCREASE' // ActionType

{
   type: increaseConstant,
   payload,
}  // Action
  • Reducer : 一个 to do 的过程 (执行Action计划的操作)
case increaseConstant: // 当 ActionType 为 'INCREASE' 时, 执行count++
  return {
    ...state,
    count: payload + 1
  }

第二问 why 为什么要使用Redux

当你不知道是否需要使用Redux的时候, 那就是不需要使用.

下面一组动图很好的描述了一个应用程序的开发过程, 及何时需要Redux.
图片来源及原文链接

  • 游戏初期阶段, 数据单向传递, 父传子

image

  • 游戏进入中期, 开始有少量非父子组件间需要通讯一些数据

image

  • 游戏进入后期, 开始需要大量的数据通讯

image

  • 此时, 就是Redux的用武之地了, 使用Redux后流程如下

image

第三问 how to 怎么使用Redux

在说使用方法之前, 我们先来从头到尾模拟一个Redux的过程, 只要理解原理, 使用起来那不是小菜一碟.

Let's go, come on baby!

image

下面我们就用一个简单的计数器的例子来模拟实现一个Redux的过程:

创建一个count组件

import React, { useState } from 'react'

const CountItem = (props) => {
  const {
    count,
    increase,
  } = props

  return (
    <>
      {count}
      <button onClick={increase}>Count++</button>
    </>
  )
}

const Count = () => {
  const [count, setCount] = useState(0)

  const increase = () => {
    setCount(count + 1)
  }

  return (
    <CountItem
      count={count}
      increase={increase}
    />
  )
}

export default Count

这样一个简单的count组件就创建好了, 现在, 我们想把对数据的操作单独封装成一个方法名为dispatch, 传递的参数为一个Action 格式: { type: xxx, payload: xxx }

封装一个Dispatch函数

const dispatch = (action) => {
  switch(action.type) {
    case 'INCREASE':
      return action.payload + 1
    default:
      break
  }
}

改写increase方法

const increase = () => {
-  setCount(count + 1)
+  setCount(dispatch({type: 'INCREASE', payload: count}))
}

这时, 我们将action对象也抽离出来, 方便复用, 新建action.js.

action.js => 返回action对象

const increaseCount = (payload) => {
  return {
    type: 'INCREASE',
    payload
  }
}

改写increase方法

const increase = () => {
-  setCount(dispatch({type: 'INCREASE', payload: count}))
+  setCount(dispatch(increaseCount(count)))
}

接下来我们把dispatch中的事件操作抽离到reducer中, 新建reducer.js.

reducer.js => 进行数据操作

const reducer = (state, action) => {
  const { type, payload } = action
  switch(type) {
    case 'INCREASE':
      return {
        ...state,
        count: payload + 1
      }
    default:
      return state
  }
}

改写dispatch函数

const dispatch = (action) => {
  const state = {
    count,
  }
  
  const newState = reducer(state, action)

  return newState
}

改写increase方法

const increase = () => {
-  setCount(dispatch(increaseCount(count)))
+  setCount(dispatch(increaseCount(count)).count)
}

接下来, 我们把set方法也拿到dispatch中, 让所有操作都在dispatch中完成.

继续改造dispatch函数, 增加setter做映射

const dispatch = (action) => {
  const state = {
    count,
  }
  
+  const setter = {
+    count: setCount
+  }
  
  const newState = reducer(state, action)
  
+  for (let key in newState) {
+    setter[key](newState[key])
+  }

-  return newState
}

改写increase方法

const increase = () => {
-  setCount(dispatch(increaseCount(count)).count)
+  dispatch(increaseCount(count))
}

这里我们可以看到, action.type是连接actionreducer的桥梁, 我们可以将actionType定义为常量单独保存.

在action中增加actionType

export const increaseConstant = 'INCREASE'

// 替换 action 和 reducer 中的 'INCREASE' 为 increaseConstant

基于现有场景, 如果我们有另一个功能, 而目前的reducer并不能帮助我们很好的把不同的功能划分开来, 我们改造一下reducer, 改造成一个对象, 用对象的key去区分功能.

改写reducer

const reducer = {
  count(state, action) {
    const { type, payload } = action
    switch(type) {
      case increaseConstant:
        return payload + 1
      default:
        break
    }
  },
}

这时我们要遍历reducer, 找到正确的key, 才能让程序正确执行, 我们新建combineReducers.js来完成这步操作.

combineReducers

const combineReducers = (reducer) => {
  return (state, action) => {
    let ret = {}

    for (let key in reducer) {
      ret[key] = reducer[key](state[key], action)
    }
    
    return {
      ...state,
      ...ret,
    }
  }
}

继续改下dispatch函数, 使其支持当前格式reducer.

改写dispatch

-  const newState = reducer(state, action)
+  const newState = combineReducers(reducer)(state, action)

至此, 一个redux的实现过程就完成了, 接下来, 我们实际用一用redux. 其实, 当完成上述操作的时候, 怎么用就已经说的差不多了.

image

Redux + React 使用

action, reducer, Count组件同上, Count组件需要简单改写下.

新建store.js

import { createStore, combineReducers } from 'redux'
import reducer from './recuder'

const initState = {
  count: 0,
}

const store = createStore(
  combineReducers(reducer),
  initState,
)

export default store

新建app.jsx, 引入store

import { Provider } from 'react-redux'
import store from './store'

const App = () => {
  return (
    <Provider store={store}>
      <Count />
    </Provider>
  )
}

export default App

改写Count组件

import React from 'react'
import { connect } from 'react-redux'
import { increaseCount } from './action'

const CountItem = (props) => {
  const {
    count,
    increase,
  } = props

  return (
    <>
      {count}
      <button onClick={increase}>Count++</button>
    </>
  )
}

const Count = (props) => {
  const {
    count,
    dispatch,
  } = props

  const increase = () => {
    dispatch(increaseCount(count))
  }

  return <CountItem count={count} increase={increase} />
}

export default connect(
  (state) => {
    return state
  },
  (dispatch) => {
    return { dispatch }
  }
)(Count)

接下来, 我们改写成hook的写法

改写Count组件

import React from 'react'
- import { connect } from 'react-redux'
+ import { useSelector, useDispatch } from 'react-redux'
import { increaseCount } from './action'

const CountItem = (props) => {
  const {
    count,
    increase,
  } = props

  return (
    <>
      {count}
      <button onClick={increase}>Count++</button>
    </>
  )
}

const Count = () => {
-  const {
-    count,
-    dispatch,
-  } = props
  
+  const count = useSelector(state => state.count)
+  const dispatch = useDispatch()

  const increase = () => {
    dispatch(increaseCount(count))
  }

  return <CountItem count={count} increase={increase} />
}

- export default connect(
-  (state) => {
-      return state
-  },
-  (dispatch) => {
-    return { dispatch }
-  }
- )(Count)

+ export default Count

至此, 本篇文章就到此结束了, 大家可以写个复杂一点的组件练习下, 比如todoList, 手动滑稽. 逃了逃了, 我要去timi去了, 我的小伙伴还等我带他上白银呢, 一帮混子, 带不动.

image

这篇关于Redux在React Hook中的使用及其原理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!