What is the story

Redux is a JavaScript state container that provides predictable state management. It’s designed specifically for the React. Js framework, but it’s not only used with React, it can be used with any interface library.

Redux’s design principles

Redux is designed and implemented in accordance with three principles, or specification limits

Single data source

The transition data of the entire application is only stored in a single Store

Read-only State

The only Store is also read-only and the application cannot modify the status data directly. The API for the Store object itself is very small, with just four methods:

  • getState(): Obtains the current status data
  • dispatch(action): Push triggers changes
  • subscribe(listener): Subscription data changes
  • replaceReducer(nextReducer):

Obviously, there is no way to set the state. The dispatch(action) is the only way to change the data, such as:

var action = {
  type: 'ADD_USER'.user: {name: 'chuonye.com'}}; store.dispatch(action);Copy the code

The dispatch method passes the action to the Redux. The action is a plain object that contains the type of operation that was triggered along with the data.

Use pure functions to perform state updates

When Redux receives an action, it uses a pure function to handle it. These functions are called Reducers:

var someReducer = function(state, action) {...return state;
}
Copy the code

The Reducer accepts the current state and action as parameters. Instead of directly modifying the original data, the Reducer returns a new state to modify the data. In general, Redux is a tool that helps applications manage state data in a unified way, following a strict one-way data flow (store-read-only) design that makes the behavior of applications predictable and easy to understand.

The basic process of using Redux

Before introducing the basic use process of Redux, we implement the case of TodoList based on the native method, and then demonstrate the use process of Redux and React-Redux respectively

Native React implementation TodoList

Example:

import React, { Component } from 'react';
import {Row,Col,Button,Divider,Input,List,} from 'antd';

class TodoList extends Component {

    constructor(props) {
        super(props)
        this.state = {
            todos: ["Basketball"."Football"."Badminton"].inpVal: ""
        }
    }

    handleChange = (e) = > {
        this.setState({ inpVal: e.target.value })
    }

    handleClick = () = > {
        const { inpVal } = this.state
        let todos = this.state.todos
        todos.push(inpVal)
        this.setState({ todos })

    }

    handleDelete = (id) = > {
        let {todos} = this.state
        todos = todos.filter((v,index) = >index ! = id)this.setState({todos})
    }

    render() {
        return (
            <div>
                <h3>React implements TodoList native</h3>
                <Divider />
                <Input
                    onChange={this.handleChange}
                    placeholder="Please enter"
                ></Input>
                <Button onClick={this.handleClick}>add</Button>
                <Divider />
                <Row>
                    <Col span={6}>
                        <List
                            bordered
                            dataSource={this.state.todos}
                            renderItem={(item, index) = > (
                                <List.Item
                                    extra={<a onClick={this.handleDelete.bind(this,index)}>delete</a>}
                                >{item}</List.Item>)}
                        >
                        </List>
                    </Col>
                </Row>
            </div>)}}export default TodoList
Copy the code

TodoList based on Redux

Install the story

yarn add redux --save
Copy the code

The concrete steps of TodoList implementation based on Redux:

  • Create an Action
    • Create in the root directoryactionFolder and create under the folderindex.jsx
    • buildactionFunction to returnactionObject, noticeactionMust containtypeattribute
    • will actionAnd export

Example:

// src/action/index.jsx
// Create an Action for Todo
const addTodoList = (iptVal) = > ({ type: 'ADD', iptVal })
// Query the current TodoList
const seleteTodoList = () = > ({ type: 'SELECT' })
/ / to monitor the Input
const InputChange = (iptVal) = > ({ type: 'INPUT', iptVal })
// Delete the Todo Action
const DeleteTodoList = (index) = > ({ type: 'DELETE', index })

module.exports = {
    addTodoList,seleteTodoList,InputChange,DeleteTodoList
}
Copy the code
  • Create the Reducer
    • Create in the root directoryreducerFolder and create under the folderindex.jsx
    • buildreducer, pay attention toreducerTwo parameters are to be received
    • The first parameter is the default and defines an initializationstate, and then do the assignment

Example:

/src/reducer/index.jsx
// 1. Initialization
const initState = {
    todos: ["Basketball"."Football"."Badminton"].iptVal: ""
}
// 2. Create the Reducer
const reducer = (state = initState, action) = > {
    let newState = Object.assign({}, state, action);
    switch (action.type) {
        case "ADD":
            const { iptVal, todos } = state
            newState.todos.push(iptVal)
            return newState
        case 'SELECT':
            return Object.assign({}, state, action)
        case 'INPUT':
            return Object.assign({}, state, action)
        case 'DELETE':
            const { index } = action
            newState.todos.splice(index, 1)
            return newState
        default:
            returnstate; }}export default reducer
Copy the code
  • Create the Store
    • Create with directorystoreAnd create under the folderindex.jsx
    • usecreateStoreSo the first argument in the function is going to bereducer
    • The importreducerSet to a functioncreateStore(reducer)
    • Will create thestoreTo export

Example:

import { createStore } from 'redux'

import reducer from '. /.. /reducer/'

const store = createStore(reducer)

export default store
Copy the code
  • Redux is used in components
    • Bind button to listen for events
    • Passes when the component has finished loadingstoreThe return value can be used to register the listener
    • throughstore.dispatch(action)Send the action

Example:

import React, { Component } from 'react';
import {
    Divider,
    Input,
    Button,
    Row,
    Col,
    List
} from 'antd'
import store from '.. /.. /store/index'

import { 
    addTodoList, 
    seleteTodoList, 
    InputChange, 
    DeleteTodoList 
} from '. /.. /.. /action/index'


class Home extends Component {

    constructor(props) {
        super(props)
        this.state = store.getState()
    }

    componentWillMount() {
        const action = seleteTodoList()
        / / send the action
        store.dispatch(action)
    }

    handleChange = (e) = > {
        const action = InputChange(e.target.value)
        / / send the action
        store.dispatch(action)
    }

    handleClick = () = > {
        const { iptVal } = this.state
        const action = addTodoList(iptVal)
        / / send the action
        store.dispatch(action)
    }

    handleDelete = (index) = > {
        const action = DeleteTodoList(index)
        / / send the action
        store.dispatch(action)
    }

    componentDidMount() {
        store.subscribe(() = > this.setState(store.getState()))
    }

    render() {
        return (
            <div
                style={{
                    width: 500.height: 500.textAlign: 'center',
                    margin: '0 auto'}} >
                <h3>Redux implementation TodoList</h3>
                <Divider />
                <Input
                    onChange={this.handleChange}
                    placeholder="Please enter"
                    style={{ width: 300.marginRight: 50 }}
                    value={this.state.iptVal}
                ></Input>
                <Button onClick={this.handleClick}>add</Button>
                <Divider />
                <Row>
                    <Col>
                        <List
                            bordered
                            dataSource={this.state.todos}
                            renderItem={(item, index) = > (
                                <List.Item
                                    extra={<span onClick={this.handleDelete.bind(this, index)} >delete</span>}
                                >{item}</List.Item>)}
                        >
                        </List>
                    </Col>
                </Row>
            </div>)}}export default Home;
Copy the code

Summary of the Redux invocation process

Basic steps:

  1. createaction
  2. sendactionreducerstore.dispatch(action)
  3. reducer(preState,action)To process the business logicreturntostore
  4. Listening to thestoreBased onstoreProvided by the APIstore.getState()Get the lateststate
action --> store.dispatch(action) --> reducer(action) --> store
Copy the code

Implement TodoList based on React-Redux

Create a project

Create-react-app demo02 CD demo02 yarn add redux -- Save yarn add react-redux -- Save yarn add antd@"^3.26.20" -- Save yarn Add the react @ "^ 16.14.0" -- saveCopy the code

Implementation steps

  1. Based on thereduxbuildstoreIn thesrccreatestoreDirectory and createindex.jsxfile
  2. createreducer/index.jsxFile, buildreducerThe responseaction
  3. throughcreateStorereducerInjection of returnstore
  4. insrc/App.jsThe introduction ofstoreAnd importProviderWrap the entire structure and pass it alongstore
  5. The introduction ofconnectTo strengthen the components,mapDispatchToPropsIt returns an object{key: method name,value: call Dispatch to send action}, passed in the componentthis.propsThe object can be obtained.connectBasic introduction to functions:
Parameter names type instructions
mapStateToProps(state,ownProps) Function This function willstoreAs data inpropsBind to a component

state: Store in redux

ownProps: props for the component
mapDispatchToProps(dispatch,ownProps) Function willactionAs apropsBind to a component

dispatch: is the store. The dispatch ()

ownProps: props for the component
mergeProps(stateProps,dispachProps,ownProps) Function DispachProps and ownProps must be merged and assigned to a component. Connect uses object.assign instead of dispachProps
options Object Customize the behavior of the Connector

Build the reducer

// src/reducer/index.jsx

const initState = {
  todos: ["Basketball"."Football"."Badminton"],}const rootReducer = (state = initState, action) = > {

  if (action.type === "ADD") {
    const { iptVal } = action
    let newState = JSON.parse(JSON.stringify(state))
    newState.todos.push(iptVal)
    return newState
  } else if (action.type === 'SELECT') {
    let newState = JSON.parse(JSON.stringify(state))
    return newState
  } else if (action.type === "DELETE") {
    const { index } = action
    let newState = JSON.parse(JSON.stringify(state))
    newState.todos.splice(index, 1)
    return newState
  } else {
    return state
  }
}

export default rootReducer
Copy the code

Building a store

// src/store/index.jsx
import { createStore } from "redux";
import reducer from ".. /reducer";
const store = createStore(reducer)
export default store
Copy the code

Import the Provider delivery Store

// App.jsx
import React, {
  Component
} from 'react';

import {
  Provider
} from 'react-redux'

import store from './store';
import AddTodo from './pages/AddTodo';
import TodoList from './pages/TodoList'
import './App.css';


class App extends Component {

  render() {
    return (
      <div style={{ width: 500.height: 500.textAlign: 'center', margin: '0 auto' }}>
        <Provider store={store}>
          <h3>The React - Reudx TodoList</h3>
          <AddTodo />
          <br />
          <TodoList />
        </Provider>
      </div>); }}export default App;
Copy the code

AddTodo components

import React, { Component } from 'react';
import {
  Input,
  Button,
} from 'antd'

import { connect } from 'react-redux'

class AddTodo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      iptVal: ""
    }
  }

  handleClick = () = > {
    const { iptVal } = this.state
    this.props.AddAction(iptVal)
  }

  render() {
    return (
      <div>
        <Input
          onChange={(e)= >This.setstate ({iptVal: e.target. Value})} placeholder=" view "style={{width: 300, default: 0.5px; default: 0.5px; default: 0.5px; default: 0.5px; default: 0.5px; 50 }} value={this.state.iptVal} ></Input>
        <Button onClick={this.handleClick}>add</Button>
      </div>); }}const mapDispatchToProps = (dispatch) = > {
  return {
    AddAction: (iptVal) = > {dispatch({type: 'ADD',iptVal})}
  }
}

export default connect(null, mapDispatchToProps)(AddTodo);

Copy the code

TodoList components


import React, { Component } from 'react';
import {
  Row,
  Col,
  List
} from 'antd'
import { connect } from 'react-redux'
class TodoList extends Component {

  handleDelete = (index) = > {
    this.props.RemoveAction(index)
  }

  render() {
    return (
      <div>
        <Row>
          <Col>
            <List
              bordered
              dataSource={this.props.todos}
              renderItem={(item, index) = > (
                <List.Item
                  extra={<span onClick={this.handleDelete.bind(this, index)} >delete</span>}
                >{item}</List.Item>)}
            >
            </List>
          </Col>
        </Row>
      </div>); }}const mapStateToProps = (state) = > {
  return state
}

const mapDispatchToProps = (dispatch) = > {
  return {
    RemoveAction: (index) = > {dispatch({type: 'DELETE',index})}
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoList)

Copy the code

Reference:

  • React-redux Chinese documentation
  • TodoApp with Redux
  • The react – the story’s official website