Recently, due to the React project, I began to learn some content about the React Family bucket. One part of the content was frequently used, so I also started to catch up on this knowledge

As the title suggests, this article is about how redux & React-Redux is used in practice

So, without further ado, let’s begin at the beginning

Who are they?

  • Personally, I think it’s a dedicated repository, you could call it a store
  • The repository is created using the createStore method in the Redux library
  • The nice thing about Redux is that unlike Vuex, which has to rely on Vue, it stands out on its own

So, the question?

  • What does react-Redux do?
    • React and Redux react and Redux react
    • Second, and importantly, it serves as a bridge between the React component and the Store repository

OK, so we know what they’re going to do, so let’s just go ahead and do it

No installation, no warehouse construction

// Install redux and react-redux NPM I redux react-redux --saveCopy the code

It’s a perfectly normal structure

How to use the

Let’s start with the simplest component. How does a component connect to a repository via React-Redux

Create a Counter. Js component in the Components folder just to add and subtract

// components/ counter. js file import React, {Component} from'react';

export default class Counter extends Component {
    constructor() { super(); This. state = {number: 0}; }render() {
        return (<div>
            <button>-</button>
            {this.state.number}
            <button>+</button>
        </div>)
    }
}
Copy the code

That’s it, the Counter component. Let’s introduce it in the index main entry file

// index.js import file import React from'react';
import { render } from 'react-dom';
import Counter from './components/Counter'; <Counter />, document.getelementByid (<Counter />, document.getelementByid ('root'));Copy the code

I forgot to mention that I created the project using the create-React-app scaffolding for convenience, so install it globally before creating the project and launching it

NPM I -g create-react-app // Create a project create-react-app project name // Start NPM run startCopy the code

This is what the project looks like when it runs

Let’s see how redux & React-Redux is used in a project for this Counter component

Use redux and React-redux

The structure of the store directory is just like what we saw at the beginning, so let me analyze what’s going on inside it

  • The actions directory
    • Here are some methods, which are easy to call in the component (more in the case of requesting data)
    • You can also use this as a place to store data
  • Reducers directory
    • This is where you get the data
  • action-types.js
    • Define the types required by various components (e.g., INIT_DATA, GET_DATA, CHANGE_TYPE)
  • index.js
    • This is where the warehouse is actually created

All right, let’s get it down

The first defines action-types

// store/action-types.js // types used by the Counter componentexport const ADD = 'ADD';
export const MINUS = 'MINUS';
Copy the code

The type constants defined in action-types are defined according to the needs of each component and belong to a one-to-one correspondence relationship

The second, again about actions.

// store/actions/counter.js // import * as types from'.. /action-types'; // Return an object containing different typesexportDefault {add(count) {// Add numbersreturn {type: types.ADD, count}; }, minus(count) {// subtract the numberreturn {type: types.MINUS, count}; }}Copy the code

Since the Counter component handles addition and subtraction operations, write down the corresponding execution method in the Counter. Js file in actions

Finnally, modify the reducer and process this action

/ / store/reducers/counter. Js / / routine method and reducer is a function / / incoming components you needtype
import * as types from '.. /action-types'; // Initialization state const initState = {number: 0};function counter(state = initState, action) {
    
    switch(action.type) {
        case types.ADD:
            return { number: state.number + action.count };
        case types.MINUS:
            return { number: state.number - action.count };
        default:
            return state;
    }
    
    return state;
}

export default counter;
Copy the code

Reducer why this?

  • The initState state is used to ensure that there is no state in the repository the first time the component is loaded
  • InitState is an initialization state, but it is the data structure that your component needs, so you need to design it well
  • An action is the state passed from the corresponding file in the Actions directory, and it looks like this{type: 'ADD', count}
  • The two parameters in counter, state, represent the past state, and action, represent the new state
  • The reducer is also called because of the reduce method of array. The two parameters in reducer are similar to the present
  • Most importantly, the first step this function does is to return the state

It’s a little early to say last, we haven’t built the warehouse yet

Moreover, we need to integrate reducer before creation, because this is only one counter, and different Reducer will be written according to different components in real projects

So in order not to conflict, we use the combineReducers method provided by Redux to merge them

Merger of reducer

Create an index.js file in the reducers to merge the Reducer

CombineReducers {combineReducers} from combineReducers {combineReducers} from'redux'; // Introduce reducer import Counter from the Counter component'./counter'; // Import other Reducer import list from the reducer'./list'; // Merge beginsexportDefault combineReducers({counter, list // other reducer});Copy the code

Let’s Go

Go to index.js under the store directory

Import {createStore} from import {createStore} from'redux'; // Import reducer from all needed controls'./reducers';

const store = createStore(reducer);
export default store;
Copy the code

Ready to take off

Ok, now that the repository is created, let’s go back to the Counter component and make some changes

// components/Counter.js

import React, { Component } from 'react'; // React-redux provides the connect method, which is a higher-order function import {connect} from'react-redux';
import actions from '.. /store/actions/counter';
+++

// export(HOC) Class Counter extends Component {HOC class Counter extends Component {renderConst {add, minus, {// count () {// count () {// count (); number } = this.props;return(<div> <button onClick={() => minus(1)}>-</button> {number} <button onClick={() => add(2)}>+</button> </div>) } }; +++ const mapStateToProps = state => { console.log(state); Reducer: {counter: {number: 0}, list: {data: []}}return {
        number: state.counter.number
    };
};

const mapDispatchToProps = dispatch => {
    return {
        add: (n) => dispatch(actions.add(n)),
        minus: (n) => dispatch(actions.minus(n))
    };
};

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Counter);
+++
Copy the code

After writing the above code, you are ready to connect the Counter component to the Store repository. Finally, let’s modify the index.js entry file so that all components can connect to the Store

A miracle is about to happen

// index.js

import React from 'react';
import { render } from 'react-dom';
import Counter from './components/Counter'; +++ // Provider is a component that contains everything, but only one child import {Provider} from'react-redux';
import store from './store'; Render (<Provider store={stroe}> <React.Fragment> {/* If there are multiple components, render(<Provider store={stroe}> <React. You have to wrap it with the React.Fragment component, which doesn't produce extra tag elements, } <Counter /> </ react. Fragment> </Provider>, document.getelementById ('root'));Copy the code

Everything’s quiet. Look at the end result

The actual project will be a little more difficult to operate than this, but it is much the same. Learning to draw inferences from one another is able to slowly and skillfully use them. Now let me show you how I wrote in the recent project, which is not good for reference only

Just to let you, slowly understand, slowly skilled, slowly use, slowly write better

Take a look at the renderings first

This is the link address

Here’s how I did it. (It’s not that hard. Take a look.)

Put into action

As you can see above, there are really only two states to manage as a recommended list

  1. Switch categories (hot search, scenic spots, food, hotel TAB)
  2. Get list data (get corresponding data according to different categories)

Let’s start with action-types

In the SRC directory,a store folder will be created, which contains the necessary contents of Actions,reducers, action-types and so on

// store/action-types.js // get the category listexport const GET_RECOMMEND_LIST = 'GET_RECOMMEND_LIST'; // Toggle categorytype
export const CHANGE_CATEGORY = 'CHANGE_CATEGORY';
Copy the code

OK, I’ve got the action type, so I’ll go ahead and bring up actions

Actions correspond to actions (methods)

/ / store/actions/how. Js / / introduction of all the types of constant import * as types the from'.. /action-types'; Request list data import {getPoiList} from'.. /.. /api'; // Export an object by defaultexportChangeCategory (params, data) {changeCategory(params, data) {letresponse; // The request is not sent if the current data already exists in the repositoryif(! Data [params.category]) {response = getPoiList({params}); }return {
            type: types.CHANGE_CATEGORY, category: params.category, key: Params.keyword, response}}, // A method for getting list data getRecommendList({params}) {let data = getPoiList({ params });
        
        return {
            type: types.GET_RECOMMEND_LIST,
            response: data,
            params
        }
    }
}
Copy the code

Okay, so that’s all we have in our Actions, just two of them

ChangeCategory not only performs TAB switching, but also optimizes requests while switching

How many reducers

/ / store/reducers/how. Js / / introduction of all the types of constant import * as types the from'.. /action-types'; // Initialize state data const initState = {pathName:' ',
    params: {},
    loading: false,
    data: {
        hot: null,
        food: null,
        hotel: null,
        scenic: null,
    },
    business: {},
    category: 'hot',
    key: 'sites'
};

function recommend(state = initState, action) {
    switch(action.type) {
        caseTypes.CHANGE_CATEGORY: const {category, response, key, params} = action;letnewState = Object.assign({}, state, { data: { ... state.data, [action['category']]: response
                }
            });
            
            return{... state, ... newState };case types.GET_RECOMMEND_LIST:
            const { pathname, params, response = {}, loading = false } = action;
            letnewState = Object.assign({}, state, { data: { ... State. Data, [category]: response // Match different types of data one by one, such as food:{response:[]}}}); // Omit some code for processing AD datareturn newState;
        default:
            return state;
    }
    
    return state;
}

export default recommend;
Copy the code

This is reducer finished, in fact, after writing more, we can feel a little bit

In fact, the above a meal operation, with three words is

  1. Define constant types (actions-types)
  2. Save data (actions)
  3. Take data and process data (reducers)

Well, the last minute is up, so let’s go straight to the component and see how it works

The Recommend component connects to the warehouse

In the same directory as Store, there is a Components folder where common components are commonly used, and Recommend is one of them

So let’s go straight to how does recommend look

// components/recommend/index.js

import React, { Component } from 'react';
import actions from '.. /.. /store/actions/recommend';
import { connect } from 'react-redux'; // The following two components are used to slide and load import ScrollLoad from'.. /.. /common/ScrollLoad';
import Loading from '.. /.. /common/Loading'; // List data render component import List from'./list';
import { CHANGE_CATEGORY, GET_RECOMMEND_LIST } from '.. /.. /store/action-types'; // Define the initialization parameters and TAB list array to facilitate rendering const initParams = {keyword:'sites', category: 'hot' };
const navList = [
    { type: 'hot', name: 'Hot search in the city', keyword: 'sites' },
    { type: 'scenic', name: 'sites', keyword: 'Scenic Spot' },
    { type: 'food', name: 'food', keyword: 'food' },
    { type: 'hotel', name: 'hotel', keyword: 'hotel'}]; Class Recommend extends Component {// First requests list data during the willMount lifecyclecomponentWillMount() { const { getRecommendList } = this.props; // Initialize data getRecommendList({params: initParams}); HandleClick = (event) => {const {changeCategory, response} = this.props; const { data } = response; const category = event.target.dataset.category; const keyword = event.target.dataset.keyword; const obj = { category, keyword }; // Change the corresponding type changeCategory(obj, data); ScrollHandle = ({page, callback}) => {const {getRecommendList, response} = this.props; const { params, category, key, data } = response;letbatch = data[category] && data[category].page + 1; const newParams = Object.assign({}, params, { batch }); newParams.category = category; newParams.keyword = key; // Load data getRecommendList({params: newParams}). Then (() => {callback(); }); }render() { const { response } = this.props; const { params, data, category } = response; const categoryData = data[category]; // Categorize datalettotalcount = categoryData && categoryData.totalcount; // List item const navItem = navlist.map ((item, I) => <li className={category === item.type?'active' : ' '}
                data-category={item.type}
                data-keyword={item.keyword}
                onClick={this.handleClick}
                key={i}>{item.name}
            </li>
        );

        return (
            <div className='recommend'>
                <ul className='recommend-nav'>{navItem}</ul>

                {totalcount ? <ScrollLoad totalCount={totalcount} scrollHandle={this.scrollHandle}>
                    <List response={response} />
                </ScrollLoad> : <Loading />}
            </div>
        );
    }
}

const mapStateToProps = state => {
    return {
        response: state.recommend
    }
};

const mapDispatchToProps = dispatch => {
    return {
        changeCategory: (params, data) => dispatch(actions.changeCategory(params, data)),
        getRecommendList: ({params}) => dispatch(actions.getRecommendList({params})
    }
};

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(RecommendList);
Copy the code

The above is roughly complete the process of adding the recommended component and connecting the warehouse. Here are two more pictures to illustrate

The following figure shows the data changes in the warehouse corresponding to the operation of switching classification

Well, well, write so much, you see also tired, thank you for your patience to watch.

For learning, we must never stop, thank you, goodbye