关于react.js:Redux在React-Hook中的使用及其原理

45次阅读

共计 4930 个字符,预计需要花费 13 分钟才能阅读完成。

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.
图片起源及原文链接

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

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

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

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

第三问 how to 怎么应用 Redux

在说应用办法之前, 咱们先来从头到尾模仿一个 Redux 的过程, 只有了解原理, 应用起来那不是小菜一碟.

Let’s go, come on baby!

上面咱们就用一个简略的计数器的例子来模仿实现一个 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. 其实, 当实现上述操作的时候, 怎么用就曾经说的差不多了.

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 去了, 我的小伙伴还等我带他上白银呢, 一帮混子, 带不动.

正文完
 0