Hello, brave friends, I am your strong mouth king xiao Wu, healthy body, not brain disease.

I have a wealth of hair loss techniques that will catapult you to the top.

A look will be written waste is my theme, food to pick the foot is my characteristics, humble in showing a trace of strong, stupid people have stupid blessing is the greatest comfort to me.

Welcome to The use and principles of Redux in React Hook.

Introduction to story

What, why and how to Redux

The first to ask whatWhat is the story

When a Web application is split into a view layer and a data layer, a Redux is a container that holds its data, essentially maintaining an object that stores the data.

  • State: a container (an object) that holds data
const initState = {
  count: 0,}Copy the code
  • Action: a want to do process (plan what kind of operation to do)
    • ActionTypeIs theActionThe description is also the connectionActionandReducerThe bridge
    • It’s essentially a function ofActionTypeandpayload(data) composed of objects
export const increaseConstant = 'INCREASE' // ActionType

{
   type: increaseConstant,
   payload,
}  // Action
Copy the code
  • Reducer: a to do process (Action plan execution)
case increaseConstant: // when ActionType is 'INCREASE', count++ is executed
  return {
    ...state,
    count: payload + 1
  }
Copy the code

The second question according toWhy use Redux

When you don’t know if you need to useReduxIt is not necessary to use.

The following set of GIFs is a good illustration of how an application is developed and when Redux is needed. Photo source and original link

  • In the early stages of the game, data is passed from parent to child

  • In the middle of the game, there are a few non-parent components that need to communicate some data

  • As the game enters its later stages, it begins to require a lot of data traffic

  • In this case, it isReduxWhere you can use it. Use itReduxThe subsequent process is as follows

How toHow to use Redux

Before we talk about how to use it, let’s simulate a Redux process from start to finish. Once you understand how it works, it’s not a piece of cake.

Let’s go, come on baby!

Let’s use a simple counter example to simulate the implementation of a Redux:

Create a count component

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

Copy the code

Now we want to wrap the operation on the data as a method called Dispatch, passing an Action format: {type: XXX, payload: XXX}

Encapsulates a Dispatch function

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

Rewrite the increase method

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

At this point, we will also pull out the action object, easy to reuse, new action.js.

Action.js => Returns the Action object

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

Rewrite the increase method

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

Next, we will remove the event operations from the dispatch to the reducer and create the reducer.js.

Js => Perform data operations on reducer

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

Rewrite dispatch function

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

  return newState
}
Copy the code

Rewrite the increase method

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

Next, we’ll take the set method to the Dispatch, and we’ll have everything done in the Dispatch.

Continue modifying the Dispatch function, adding setters to do the mapping

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
}
Copy the code

Rewrite the increase method

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

As we can see here, action.type is the bridge between action and Reducer. We can define actionType as a constant and save it separately.

Add actionType to action

export const increaseConstant = 'INCREASE'

// Replace 'INCREASE' in action and Reducer with increaseConstant
Copy the code

Based on the existing scenario, if we have another function, but the current reducer cannot help us to divide different functions well, let’s transform the reducer into an object, and use the key of the object to distinguish functions.

Rewrite the reducer

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

In this case, we need to traverse the Reducer and find the correct key so that the program can be executed correctly. We create combInereducers.js to complete this operation.

combineReducers

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

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

Continue to change the dispatch function to support the current format reducer.

Rewrite the dispatch

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

At this point, a redux implementation is complete. Next, let’s actually use redux. In fact, when the above operation is done, how to use it has already said about.

Redux + React

The action, Reducer, and Count components are the same as above. The Count component needs to be simply rewritten.

The new store. Js

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

const initState = {
  count: 0,}const store = createStore(
  combineReducers(reducer),
  initState,
)

export default store
Copy the code

Create app.jsx and introduce the Store

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

const App = () = > {
  return (
    <Provider store={store}>
      <Count />
    </Provider>)}export default App
Copy the code

Overwrite the Count component

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)

Copy the code

Next, let’s rewrite it as hook

Overwrite the Count component

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

Copy the code

That’s the end of this article, and you can write a more complex component exercise, such as todoList, manually funny. I’m going to Timi. My little buddy is waiting for me to take him to the silver. A bunch of bastards.