When using Redux in a React project, there are a few main libraries that are typically involved:


  1. redux: This is the core Redux library that provides the basics for creating stores, distributing actions, and processing reducers.

  2. react-redux: This library provides bindings between Redux and React, making it easy to use state from the Redux store in React components.

 Installation of related libraries

npm install redux react-redux
# or
yarn add redux react-redux

 Creating a Redux store


To use Redux, you first need to create a Redux store, which is a “container” for your application’s global state. Here is a simple example of a store setup:

import { createStore } from 'redux';
import rootReducer from './reducers'; 
const store = createStore(rootReducer);

export default store;

 1. Using Redux in Functional Components


Using Redux in a functional component usually involves the following steps:


  1. Connecting to the Redux store: Use the useSelector and useDispatch hooks provided by react-redux to connect to the Redux store.

  2. Select State: Use the useSelector hook to select the state you want from the store.

  3. Distribute action: Use the useDispatch hook to distribute action to update the state in the store.

 1.1 Recommended project document structure


If the project is using Redux as the state manager, a recommended file organization is shown below:

src/
|-- actions/
|   |-- index.js
|-- reducers/
|   |-- index.js
|   |-- someReducer.js
|-- components/
|   |-- SomeComponent.js
|-- store/
|   |-- index.js
|-- App.js


The document organization structure described above helps keep the project clear and maintainable:


  • actions folder contains all action creators, which are functions used to create and distribute actions.

  • reducers folder contains all the reducer functions that update the state of the application based on incoming actions.

  • components folder contains all the React components that are responsible for rendering the UI and possibly interacting with the Redux store.

  • store The folder contains the logic for creating the Redux store, which is a “container” for applying global state.


With this structure, it is easy to find and manage all the code related to state management, which improves the readability and maintainability of the code. At the same time, this structure also follows the principle of separation of concerns, which makes different types of code (such as actions, reducers, components, etc.) organized in different folders for easy development and maintenance.


In addition, the following sequence is recommended for building a Redux data stream: actions/index.js -> reducers/someReducer.js -> reducers/index.js -> store/index.js -> App.js -> components/SomeComponent.js

 1.2 Code Examples


actions/index.js: building type enumerations and actionCreators

export const SOME_ACTION = 'SOME_ACTION';
export function someAction(payload) {
  return { type: SOME_ACTION, payload };
}


reducers/someReducer.js: single reducer, three components type initialState switch

import { SOME_ACTION } from '../actions';
const initialState = { data: null };
export function someReducer(state = initialState, action) {
  switch (action.type) {
    case SOME_ACTION:
      return { ...state, data: action.payload };
    default:
      return state;
  }
}


reducers/index.js:combine reducer -> rootReducer

import { combineReducers } from 'redux';
import someReducer from './someReducer';

const rootReducer = combineReducers({
  someReducer
});

export default rootReducer;


store/index.js: the core step, creating the store

import { createStore } from 'redux';
import rootReducer from './reducers'; 

const store = createStore(rootReducer);

export default store;

 App.js: top-level injection

import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import SomeComponent from './components/SomeComponent';

function App() {
  return (
    <Provider store={store}>
      <SomeComponent />
    </Provider>
  );
}

export default App;

components/SomeComponent.js: data

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { someAction } from '../actions';
export function SomeComponent() {
  const dispatch = useDispatch();
  const data = useSelector(state => state.someReducer.data);
  const handleClick = () => {
    dispatch(someAction('New data'));
  };
  return (
    <div>
      <p>{data}</p>
      <button onClick={handleClick}>Update Data</button>
    </div>
  );
}

 1.3 Code Interpretation


  1. actions/index.js: In this file, we define an action type SOME_ACTION and a corresponding action creator function someAction . SOME_ACTION This is a string constant that identifies a specific action in the reducer. The someAction function takes a payload parameter and returns an action object that contains two properties, type and payload . The property identifies the type of the action, while the property contains the type of the action. type The payload property identifies the type of the action, and the property contains the data associated with the action.


  2. reducers/someReducer.js: This file defines a reducer function called someReducer . This function takes the current state and an action object as arguments and updates the state based on the type of the action. In this example, if the type of the action is SOME_ACTION , then the reducer returns a new state that contains the incoming payload data. If the action is not of type SOME_ACTION , then the reducer returns the original state.


  3. reducers/index.js: In this file, we use Redux’s combineReducers method to merge all of our reducers into a single root reducer. The advantage of this is that we can easily manage multiple reducers, and each reducer is responsible for managing only a portion of the application state. In this example, we only have one reducer, someReducer , but we still use combineReducers to organize it so that we can easily add more reducers in the future.


  4. store/index.js: In this file, we use the core function createStore in conjunction with rootReducer to create the root store and export it.


  5. App.js: In this file, we introduce react , Provider of react-redux , store which we created, and our SomeComponent component. Provider is a Redux component that makes the Redux store accessible through React’s context API at any level in the application component tree. We wrap the entire application by using store as an attribute of Provider so that any component in the application can access this store .


  6. components/SomeComponent.js: In this React component file, we use two React-Redux hooks, useSelector and useDispatch , to connect to the Redux store. The useSelector hook is used to select the state fragment we need from the store, and the useDispatch hook is used to distribute the actions. Inside the component, we define a handleClick function which is called when the user clicks the button and distributes a someAction action which updates the state in the store. The rendering part of the component displays data based on the current state and a button that the user can click to trigger the state update.

 2. Using Redux in class components


Using Redux in a class component usually involves the following steps:


  1. Connecting to the Redux store: Use the connect function provided at react-redux to connect to the Redux store.

  2. Select State: Select the desired state from the store in the mapStateToProps function.

  3. Distribute action: Define a method to distribute an action in the mapDispatchToProps function to update the state in the store.

 2.1 Recommended project document structure


For projects using class components and Redux, the recommended file organization remains similar to that of functional components:

src/
|-- actions/
|   |-- index.js
|-- reducers/
|   |-- index.js
|   |-- someReducer.js
|-- components/
|   |-- SomeComponent.js
|-- store/
|   |-- index.js
|-- App.js


Maintaining the same file structure contributes to the uniformity and maintainability of the project.

 2.2 Code Examples


The code in the actions/index.js and reducers/ folders is the same as the examples in the functional component, so it will not be repeated.


store/index.js: The code that creates the store also remains the same.


App.js: still need to use Provider at the top level to wrap the app.

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

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <SomeComponent />
      </Provider>
    );
  }
}

export default App;


components/SomeComponent.js: Connect to the Redux store using the connect function.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { someAction } from '../actions';

class SomeComponent extends Component {
  handleClick = () => {
    this.props.dispatchSomeAction('New data');
  };

  render() {
    return (
      <div>
        <p>{this.props.data}</p>
        <button onClick={this.handleClick}>Update Data</button>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  data: state.someReducer.data
});

const mapDispatchToProps = dispatch => ({
  dispatchSomeAction: payload => dispatch(someAction(payload))
});

export default connect(mapStateToProps, mapDispatchToProps)(SomeComponent);

 2.3 Code Interpretation


components/SomeComponent.js: In this class component file, we use the connect function to connect to the Redux store. The connect function takes two arguments: mapStateToProps and mapDispatchToProps . mapStateToProps It is a function that takes the state of the entire store and returns an object whose properties are passed to the component’s props. In this example, we select the someReducer.data state from the store and pass it to the component as the data property. mapDispatchToProps It is also a function that receives a dispatch function as an argument and returns an object whose properties are functions, and these functions call dispatch to distribute actions. in this example, we define a dispatchSomeAction function that receives a payload argument and distributes a someAction action. finally, we use the connect function to apply these two mapping functions to our component, thus creating a component that is connected to the Redux store.


This means that you need to use the HOC to inject two properties into the original component’s props, one for data and one for dispatchSomeAction , which represent references to existing data and methods for modifying the state, respectively. As you can see, the class component is injected rather than hooked. But the basic steps are exactly the same!

By hbb

Leave a Reply

Your email address will not be published. Required fields are marked *