Writing in the front

In order to make the usage of redux clearer, the article will teach you the whole process of redux step by step, from the shallow to the deep, more suitable for beginners, veteran drivers can directly overtake

Note: The project is based on TypeScript. Most of the sample code is written using ES6 syntax. If you don’t know how to write type checking, you can also go to the TypeScript website and try it out

1. Download the dependencies required by Redux

$ npm install redux react-redux

Copy the code

Once you have downloaded the project, create a folder in the project SRC directory. In accordance with the development principles, this folder will be called redux. You can name it as you like (😄 if you don’t need to maintain the project).

img

3. Create a store. Ts file in the newly created Redux folder

//store.ts

import { createStore } from 'redux'const initState = {  name: 'yydbb'Const reducer = (state = initState, action: any) => {// Reducer = (state = initState, action: any);return state}const store = createStore(reducer)export default store;

Copy the code

4. My guess is that your first reaction to the sample code above is: That’s it? Super simple? Yes, it’s that simple. Here’s how to use kangkang

Reducer is a pure function that receives two parameters, the first is a global initialization state and the second is action, which is an object that must include type and can be supplemented with other parameters to modify state. Finally, a new state is returned. After our unremitting efforts, Example code is as follows:

import { createStore } from 'redux'const initState = {  name: 'yydbb'Const reducer = (state = initState, action: any) => {// Reducer = (state = initState, action: any);

  if (action.type === 'CHANGE_NAME') {    letParse (json.stringify (state))// Rough deep copy myState.name = action.namevalreturn myState  }  return state}const store = createStore(reducer)export default store;

Copy the code

Compared to the previous code, what have we added to Kangkang

We have defined an interface that limits the data type of the reducer second parameter action. If other development in the project uses reducer, it must use this format. Otherwise, we’ll shut him down and let him find his own bugs

interface Action{  

  type: string,  

  ageVal:number

}

Copy the code

Next, we expanded the reducer function’s processing logic. We believe that the reducer function has no problem for everyone to understand (if there is any problem, please go back to learn basic JavaScript syntax).

const reducer = (state = initState, action: Action) => {

  if (action.type === 'CHANGE_NAME') {

    letParse (json.stringify (state))// Rough deep copy, not recommended in real projects

    myState.name = action.nameVal

    return myState

  }

  if (action.type === 'CHANGE_AGE') {

    letParse (json.stringify (state))// Rough deep copy, not recommended in real projects

    myState.age--

    return myState

  }

  return state

}

Copy the code

At this point, redux is ready to go. You heard me right. Let’s try it

5. Now we are going to use redux in the page we just wrote. We don’t expect 😄

  • Introduce Redux in the login.tsx page
import React from "react";

import store from '. /.. /redux/store'

class Login extends React.PureComponent<any, any> {  state = {    age: 0,    name: 'enen'  }  componentDidMount() {    const { name, age } = store.getState()    this.setState({      age,      name    })  }  public render() {    return(<div> I am {this.state.name} I am {this.state.age} </div>); }}

Copy the code
  • The key API in store is getState(). This method takes the value of initState defined in our store.ts folder and returns the result on the page:
img
  • Now our redux has been able to be applied on the page, but it can only be used, can not be modified, smart friends have started to think about it, next let’s come to kangkang how to modify it, after we work overtime to modify, login. TSX page has become unknown
class Login extends React.PureComponent<any, any> {

  state = {

    age: 0,

    name: 'enen'

  }

  componentDidMount() {

    const { name, age } = store.getState()

    this.setState({

      age,

      name

    })

  }



  public render() {

    return (

      <div>

I am {this.state.name} I am {this.state.age}

<button onClick={this.changeName}>

<button onClick={this.changeAge}>

      </div>



    );

  }

  changeName = () => {

    const action = {

      type'CHANGE_NAME'.

      nameVal: 'happy'

    }

    store.dispatch(action)

    console.log(store.getState());

  }

  changeAge = () => {

    const action = {

      type'CHANGE_AGE'

    }

    store.dispatch(action)

    console.log(store.getState());

  }

}

Copy the code

Paste our modified store.ts

import { createStore } from 'redux'



const initState = {

  name: 'yydbb'.

  age: 18

}

interface Action {

  type: string,

ageVal? : number,

nameVal? : string

}



Reducer is a pure function. If the input parameters are the same, the return value must be the same. Please refer to the official document for the specific definition

const reducer = (state = initState, action: Action) => {

  if (action.type === 'CHANGE_NAME') {

    letParse (json.stringify (state))// Rough deep copy, not recommended in real projects

    myState.name = action.nameVal

    return myState

  }

  if (action.type === 'CHANGE_AGE') {

    letParse (json.stringify (state))// Rough deep copy, not recommended in real projects

    myState.age--

    return myState

  }

  return state

}

const store = createStore(reducer)



export default store;

Copy the code

Page operation effect is as follows:

img

We have operated five times in total, including one changeName and four changeAge. As shown in the picture, you can see that the printed result is what we want, but the result displayed on the interface is not what we want. Why is this? Vuex is much better than this. I submitted a commit and immediately saw the updated value. How could redux not be there?

componentDidMount() {

    store.subscribe(() => {

      const { name, age } = store.getState()

      this.setState({

        age,

        name

      })

    })

  }

Copy the code

Here we don’t care why we write it like this first kangkang effect:

img

So amazing? Back to kangkang, you will find the mysterious word subscribe, copy to Baidu translation (no advertising meaning, we like to use whatever) to see what it means, originally is the meaning of subscribe, so here we can understand that the page gets redux data at the same time subscribe to it. The advantage of this is that if the data changes later, the page can see the latest data. The disadvantage is that it is equivalent to the watch in Vue. If we do not log out, we will always consume resources in memory. Of course, it is not recommended for the time being.

let unsubscribe =

      store.subscribe(() => {

        const { name, age } = store.getState()

        this.setState({

          age,

          name

        })

      })

    // unsubscribe()

Copy the code

Summary:

Now that we’ve seen the simplest use of Redux, we’re going to split store.ts and do a little optimization. Here’s what we optimized the file directory:

img

We can see that there is a reducer. Ts file and an actiontype. ts file.

import { CHANGE_NAME, CHANGE_AGE } from './actionType'

const initState = {

  name: 'yydbb'.

  age: 18

}

interface Action {

  type: string,

ageVal? : number,

nameVal? : string

}

Reducer is a pure function. If the input parameters are the same, the return value must be the same. Please refer to the official document for the specific definition

const reducer = (state = initState, action: Action) => {

  if (action.type === CHANGE_NAME) {

    letParse (json.stringify (state))// Rough deep copy, not recommended in real projects

    myState.name = action.nameVal

    return myState

  }

  if (action.type === CHANGE_AGE) {

    letParse (json.stringify (state))// Rough deep copy, not recommended in real projects

    myState.age--

    return myState

  }

  return state

}

export default reducer

Copy the code

The actiontype. ts file contains the following contents:

export const CHANGE_NAME = 'CHANGE_NAME'

export const CHANGE_AGE = 'CHANGE_AGE'

Copy the code

Actiontype. ts’s main purpose is to standardize type constants and reduce bug rates

The content of the split store.ts file is as follows:

import { createStore } from 'redux'

import reducer from './reducer'



const store = createStore(reducer)



export default store;

Copy the code

Are you happy, like, four lines of code? (Add that there can only be one store in a project.)

React-redux is a react-redux that can be used on every page of a store. It is a react-redux that can be used on every page of a store

Here is the rewritten index.tsx

import React from "react";

import ReactDOM from "react-dom";

import { Provider } from 'react-redux'

import store from './redux/store'

import "./index.css";

import AppRouter from "./router/router";

ReactDOM.render(

  <React.StrictMode>

    <Provider store={store}>

      <AppRouter />

    </Provider>

  </React.StrictMode>,

  document.getElementById("root")

);

Copy the code

Two places:

  • Import the Provider component from the React-Redux
  • The introduction of the store
  • Wrap the Provider component around the page route passing store as a parameter to all routes
  • You can then use the store data on each page without importing the store

Here is the rewritten login.tsx

import React from "react";

import { connect } from 'react-redux'



class Login extends React.PureComponent<any, any> {

  state = {

    age: 0,

    name: 'enen'

  }

  componentDidMount() {

    const { name, age } = this.props

    this.setState({

      age,

      name

    })

  }

  componentDidUpdate() {

    console.log(this.props.name, this.props.age);

  }



  public render() {

    return (

      <div>

I am {this.state.name} I am {this.state.age}

<button onClick={this.props. ChangeName}> </button>

<button onClick={this.props. ChangeAge}>

      </div>

    );

  }

}





const mapStateToProps = (state: any) => {

  return {

    age: state.age,

    name: state.name

  }

}

const mapDispathToProps = (dispatch: any) => {

  return {

    changeAge() {

      const action = {

        type'CHANGE_AGE'

      }

      dispatch(action)

    },

    changeName() {

      const action = {

        type'CHANGE_NAME'.

        nameVal: 'happy'

      }

      dispatch(action)

    }

  }

}

export default connect(mapStateToProps, mapDispathToProps)(Login)

Copy the code
  • The connect API takes two parameters, as shown in the figure above, and maps the state and reducer operations from the store to the props. Now we write both dispath operations to mapDispathToProps. This makes our pages less logical and clearer. For this usage we must write more, for a time to understand, learn to use first, and then in-depth understanding
  • We print the modified value in the life Cycle componentDidUpdate and find that it is real-time, but the page is not updated in real time
img

To find a simple and crude solution (the author is also exploring for a better solution), assign name and age again in the life cycle of componentDidUpdate to achieve the desired effect, or directly use props. This is real-time, and the assignment here is for the possibility of other operations later

componentDidUpdate() {

    const { name, age } = this.props

    this.setState({

      age,

      name

    })

    console.log(this.props.name, this.props.age);

  }

Copy the code

The effect is as follows:

img

As you can see, each operation prints twice, because every time you change the state of the page, the page triggers the componentDidUpdate life cycle, so you choose to handle listening here to achieve the same effect of subscribe

Write at the end:

  • After reading this article, you should be able to grasp the usage of redux
  • Redux also has a lot of plugins, which are just for expanding the functionality. If you’re interested, you can think about it yourself
  • Typesetting is a little messy, sorry, feel good everyone a thumbs-up ~😄