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