Redux is so simple

Time:2020-10-25

Redux is a JavaScript state container that providesPredictabilityState management of.

What is predictability? My understanding is that according to a fixed input, there must be a fixed result.

Redux is specially developed for react, but it is not only used for react, but can be used for any interface library.

motivation

With the popularity of single page application, more and more states need to be managed in web app. These states may come from server side, user input data, user interaction data, current UI state, local cache data, etc. How to manage these data in an orderly way has become a difficult problem in front-end development.

Core concepts

Three principles

Single data source

Using the Redux program, all States are stored in a single data source store, similar to a huge object tree.

State is read-only

The state is read-only, and the only way to change the state is by triggering an action

Using pure functions to perform modifications

To describe how action changes the state tree, you need to write reducers.

Reducers are pure functions that interface with current state and action. Just return the corresponding state according to the action. And there has to be a return.

The return result of a function only depends on its parameters, and there are no side effects in the execution process. We call this function a pure function

Basics

action

As the name suggests, an action is an action, which is to modify the value of state through an action. It’s also the only way to modify the store.

Action is essentially a common JS object. We agree that this object must have a field type to represent our action name. In general, we use a constant to represent the value of type.

In addition, we will pass in the corresponding value of what we want the state to look like through action, so the action here may look like this

{
    type: 'TOGGLE_TODO',
    index: 5
}

Reducer

Action only describes the fact that something has happened, but it doesn’t say what changes should be made. This is what the reducer needs to do.

As a pure function, it is not recommended to use any operation with side effects internally, such as operating external variables, any operation that causes the same input but inconsistent output.

If we have more reducers and are more complex, we can’t put all the logic into one reducer. At this time, we need to split the reducers.

Fortunately, Redux provides an API called combinereducers API.

store

Store is the only data source for Redux applications. We call the createstore API to create the store.

Redux case out of react

Basic use of store and reducer

The first step is to build the development environment, which will not be introduced here. Refer to the previous article and teach you how to use react to develop calendar components and build the environment

Set up the environment and switch to the directory

npm install redux --save

hold index.tsx Change to the following code.

import { createStore, combineReducers, applyMiddleware } from 'redux'

var simpleReducer = function(state = {}, action) {
  return {
    user: {
      name: 'redux'
    }
  }
}

var store = createStore(simpleReducer)

console.log(store.getState())

We see an object printed by the console that contains user information.

How many APIs do we use?createStoreCreate a store,store.getState()Get the store, which is the root node of the only data source.

As we mentioned above, there may be more cases of action. Redux also providescombineReducersApi。 If we have multiple reducers, we can use them.

Let’s create multiple reducers to test. The code is as follows:

import { createStore, combineReducers, applyMiddleware } from 'redux'

function user(state = {name: 'redux'}, action) {
  switch (action.type) {
    case 'CHANGE_NAME':
      return {
        ...state,
        name: action.name
      }
  }

  return state
}

function project(state = {name: 'min-react'}, action) {
  switch (action.type) {
    case 'CHANGE_NAME':
      return {
        ...state,
        name: action.name
      }
  }

  return state
}


var rootReducer = combineReducers({
  user,
  project
})

var store = createStore(rootReducer)

console.log(store.getState())

As expected, we get the root store with two fields.

Combined with view

The first step is to transform the HTML to look like this and add a little tag

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <div id="userName"></div>
    < input id = "usernameinput" / > < button id = "usernamebutton" > change username < / button >
    <script></script>
</body>
</html>

Second, modify index.tsx , as follows

import { createStore, combineReducers, applyMiddleware } from 'redux'
import { func } from 'prop-types'

function user(state = {name: 'redux'}, action) {
  switch (action.type) {
    case 'CHANGE_USER_NAME':
      return {
        ...state,
        name: action.name
      }
  }

  return state
}

function project(state = {name: 'min-react'}, action) {
  switch (action.type) {
    case 'CHANGE_PROJECT_NAME':
      return {
        ...state,
        name: action.name
      }
  }

  return state
}


var rootReducer = combineReducers({
  user,
  project
})

var store = createStore(rootReducer)

function render(state = store.getState()) {
  var $userName = document.getElementById('userName')
  $userName.innerHTML = state.user.name
}

render()

console.log(store.getState())

We see that the page correctly displays the name of our user. The next step we need to do is to change the value of the store through the user’s operation, and then trigger the update of the view.

So we added this Code:

store.subscribe(function() {
  render()
})

//Binding user events
var $userNameInput = document.getElementById('userNameInput')
var userNameButton = document.getElementById('userNameButton')
userNameButton.onclick = function() {
  var value = $userNameInput.value
  store.dispatch({
    type: 'CHANGE_USER_NAME',
    name: value
  })
}

We see that after saving, when we enter the value and click change, the value of the page changes.

But the console reported an error,TS2339: Property 'value' does not exist on type 'HTMLElement'.This is due to the failure of typescript strong type verification. Just add this code

var $userNameInput = document.getElementById('userNameInput') as HTMLInputElement

See, Redux is that simple.

All other upper level applications are developed on this basis, so the steps to develop a Redux application are

  1. Define action and its corresponding reducer
  2. Monitor the change of store and provide callback function
  3. Dispatch an action and wait for good luck to happen.

Combined with react and other view class libraries, the development steps are the same.

Advanced applications

Asynchronous action

We have also seen that our reducer can only be used for synchronous applications. If we need to do some delay operations in the reducer, what can we do

The community has a mature class library for this event

npm install redux-thunk --save

Redux itself has improved a good extension mechanism, namely middleware. This is similar to express middleware.

//Introducing a new class library
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'

...
//Make the following changes to the store section
const finalCreateStore = compose(applyMiddleware(thunk))(createStore)
const store = finalCreateStore(rootReducer, {})

The function of Redux thunk is to make the dispatch method not only receive action objects, but also contain a method. We can call asynchronous code inside this method

We modified the DOM event part as follows

userNameButton.onclick = function() {
  var value = $userNameInput.value
  store.dispatch<any>(function(dispatch, getState) {
    setTimeout(() => {
      dispatch({
        type: 'CHANGE_USER_NAME',
        name: value
      })
    }, 2000)

  })
}

We can see that the page elements did change after 2S. In the actual business, we can do some asynchronous operations here.

As for Redux principle, as well as the source code and middleware source explanation, you can refer to my other article to read Redux source code

Recommended Today

Blog based on beego, go blog

Go Blog A beego based development, can quickly create personal blog, CMS system Include functions see Official website of go bloggo-blog.cn Demo siteleechan.online Update log time function January 23, 2020 New top post function February 2, 2020 New custom navigation function February 4, 2020 New site announcement function February 6, 2020 New link module February […]