React learning --- detailed explanation of the use of Redux on the ninth day (1)

Table of contents:

1 The core idea of ​​Redux

2 Basic use of Redux

3 React combined with Redux

4 Asynchronous operation of Redux

5 redux-devtool

6 module splitting of reducer

1. The core idea of ​​Redux

for example:

The following figure is a pure function, each input has a definite output, and will not be affected by external variables

This is not a pure function, because the count in the function can be changed, but the definite input of the function cannot get a definite output , and the output is affected by external variables. 

The side effect is the operation of modifying external variables during the execution of the function: the function can use variables, but cannot modify external variables

 The process is that the dispatch dispatches events to the reducer, and then the reducer returns the new state to the store (because the reducer is a pure function, it is not possible to modify the state directly through state.xxx = action.xxx, you need to return to copy the state, and then modify the copied state, Finally replace the original state)

 

 

 The first is a pure function, the second and third are not pure functions

 

 

 

 

 

Second, the basic use of Redux

The regular redux configuration is these 4 files, and the following will give examples of how to use the current version of redux:

Use redux directly in node, first create a store folder, and create 4 files below, the first is to create a store file; the second is a file to store strings, the third is to store action files, and the fourth One is the reducer file.

Enter the code in the terminal:

//用于创建package.json
yarn init -y

//下载redux的库,相当于在项目里面install
yarn add redux

 

The first is the file index.js that creates the store:

const { createStore } = require("redux")
const reducer =  require("./reducer.js")

// 创建的store
//将reducer和默认值(initialState)放到一个独立的reducer.js文件中, 而不是在index.js 避免index.js太占内存
const store = createStore(reducer)

module.exports = store

The second is the file constants.js that creates string constants:


//由于存储常量的文件   
//actionCreators和reducer函数中使用字符串常量是一致的, 所以将常量抽取到一个独立constants的文件中
const ADD_NUMBER = "add_number"
const CHANGE_NAME = "change_name"

module.exports = {
  ADD_NUMBER,
  CHANGE_NAME
}

The third is the file actionCreator.js that creates functions and methods for modifying store data:

//将派发的action生成过程放到一个actionCreators函数中
//由于存放action事件的文件,将定义的所有actionCreators的函数, 放到一个独立的文件中: actionCreators.js
const { ADD_NUMBER, CHANGE_NAME } = require("./constants")

//将派发的action生成过程放到一个actionCreators函数中

//actionCreators里面的changeNameAction方法运用了属性增强写法
//由于箭头函数没有逻辑代码,只有return内容的话,是可以不用写return,直接写要返回的内容
//这里相当于直接返回一个对象数据,所以不用写return
const changeNameAction = (name) => ({
  type: CHANGE_NAME,
  name
})

const addNumberAction = (num) => ({
  type: ADD_NUMBER,
  num
})


module.exports = {
  changeNameAction,
  addNumberAction
}

The fourth is to create the data stored in the store, the file reducer.js of the reducer:

const { ADD_NUMBER, CHANGE_NAME } = require("./constants")

// 初始化的数据
const initialState = {
  name: "why",
  counter: 100
}

// 定义reducer函数: 纯函数
// 两个参数: 
// 参数一: store中目前保存的state
// 参数二: 本次需要更新的action(dispatch传入的action)
// 返回值: 它的返回值会作为store之后存储的state
function reducer(state = initialState, action) {
  //用switch的性能比if else好
  switch(action.type) {
    case CHANGE_NAME:
      //这里用到return是因为我们不能直接修改initialState里面的数据,那样子没
      //办法做到数据响应式,所以需要先拷贝一份原数据修改数据,再替换掉原来的数据
      //直接修改数据是不对的,直接修改数据的代码一般都是这样子:state.xxx = xxx
      return { ...state, name: action.name }
    case ADD_NUMBER:
      return { ...state, counter: state.counter + action.num }
    default:
      // 没有新数据更新, 那么返回之前的state
      return state
  }
}

module.exports = reducer

Then how to use the data stored by redux (in the required js file):

//这里简写了,我们获取的是store底下的index.js文件
//这个文件就是正在使用redux里面的数据
const store = require("./store")

const { changeNameAction } = require("./store/actionCreators")

//后面这是没有actionCreators时候的写法store.dispatch({ type: "change_name", name: "kobe" })
//actionCreators里面的changeNameAction方法运用了属性增强写法
//每次调用dispatch都会重新执行reducer.js里面的reducer函数
store.dispatch(changeNameAction("curry"))

//这个方法可以获取所有变量
console.log(store.getState())

//这个方法可以在每次有任何变量发生改变的时候打印一次所有变量
const unsubscribe = store.subscribe(() => {
    console.log("订阅数据的变化:", store.getState())
  })

  //取消订阅的方法
  unsubscribe()

Run the code in node (the listed code runs directly in node):

node xxx.js

This is the same operation as using redux in the react component. Get the value of the counter in the store through store.getSate().counyer, subscribe to subscribe once the value of the store changes, and dispatch to execute the change of the store variable. (not recommended)

Using redux for the above components is very cumbersome and can be optimized through high-order functions: (this method is important for class components, and the way of writing will change when there are hooks later)

1. Download this high-level component through the community

npm install react-redux

2. Introduce react-redux Provider package app in index.jsx of APP

3. Introduce store to Provide to provide data

 4. The data using the store in the component needs to introduce the high-level component connect, which is used to wrap the component when it is output, and the first bracket of the high-level component of the connect is to use your component when the value of the store changes. The component is updated, otherwise it is not updated, and the second bracket puts this component. And the value of using the store needs to pass 

const { xxx } = this.props to get the required value. There are two parentheses in connect because the first one is equivalent to the parameter of the function, and the second function is that the output of connect is a function that also needs parameters.

5. After the data of the store is introduced between the components, the method of modifying the state of the store needs to be called. At this time, decoupling is used

6. The method of modifying the value of the state variable of the store mentioned above is a synchronous method. The following explains how to use the asynchronous method to request data from the server and share it with all other components

 Send axios request specifically in a component

 It is unreasonable to put the asynchronous operation above into a component, the process of requesting data cannot be controlled, and since the data is finally put into the state of the store, it is meaningless to request data from other components into the store, so we need to think Ways to put asynchronous request data in the store

      (1) Component code that needs to use asynchronous requests

      

(2) actionCreators in the store. js needs to let the output function, but can only return the object, so you need to download the middleware redux-thunk

npm install redux-thunk

Introduce thunk in the index.js of the store and use E:\webstudy\reactstudy\reduxone\src\store\index.js

If you want to use multiple middleware you can do this 

(3) Then there is the code in actionCreators.js

The use of two debugging tools:

1. Download:

(1) Download react-devtool and redux-devtool in Chrome's plug-in store

 

(2) Find react-devtool and redux-devtool from GitHub, but the version is very low, then load the extension in the upper left corner to decompress and open it.

 2. Use:

Component, profiler and redux are all just downloaded plugins

 component can display the code structure

 redux tool: Since this is a debugging tool used in the development stage, it is generally closed in the production stage, so the normal situation is to see the content in redux, how to open this tool?

Write the code in index.js under the store folder. At the same time, you need to use the enhanced function componentEnhancers to wrap applyMiddleware(). Compose needs to be imported from redux

 

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

 

In the production environment, you need to delete window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ to turn off redux-devtool and see the content in redux.

const composeEnhancers = compose;

The action in the redux tool can see all the methods and functions

 

state can see all variables:

 

Diff can see what the data changed from to that data

test can write test code:

 

trace can help us track where the code is executed (default is off):

 The way to open it is to add code inside:

 

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({trace:true}) || compose;

 

 

 

 

3. React combined with Redux

 

 

4. Asynchronous operation of Redux

 

 

 

五、redux-devtool

6. Module splitting of reducer

The same as the previous state manager, there will be modules that store data and functions of different files. Here we need to create a module with the component name as the file name in the store folder:

 Create an index.js under the store to combine the counter and home reducers in the above figure, and use combineReducers in redux to combine the reducers of multiple modules

 

 

Since it is a combination of multiple modules, it is necessary to add the module name when introducing a certain data in many components

 ​​​​​​​

 The action's method also needs to be called again from the module

 

 

 

 

 

 

The figure below is equivalent to the merger of the above figure

 

Guess you like

Origin blog.csdn.net/weixin_56663198/article/details/129015304