Redux instance – simple to-do list

Time:2020-10-21

Write it at the front

The example of “to-do list” is recommended by Redux documents, but for newcomers, the relevant explanations of official documents and online blogs are not very good. There is no idea to analyze the whole process of code implementation, which makes me very headache when I study. Looking at all kinds of articles that don’t separate files, sort out the data flow, and don’t explain the code ideas, I decided to write a rudimentary example of Redux – a simple to-do list.
github

Effect display

Redux instance - simple to-do list

Before you start

Redux’s basic principles

  • Application widestateIs stored as aobject treeAnd this oneobject treeOnly exists in the only onestoreMedium.
  • The only changestateThe way is throughdispatchtriggeractionactionIt is a common object that describes the modification intention, such as:{ type: add, value }
  • WhenstorereceivedactionAfter that, it started inreducerFinally, a new one is returnedstate
  • Redux tutorial, official document

command line

create-react-app redux-todolist
cnpm i redux react-redux -S

directory structure

Redux instance - simple to-do list

get ready

Using provider

External to the root componentproviderPackage, you can get all the componentsstate

// App.js
import React from 'react';
import { Provider } from 'react-redux';
Import addtodo from '. / containers / addtodo'; // note the location of the reference
Import showlist from '. / containers / showlist'; // note the location of the reference
Import filter from '. / containers / filter' // note the location of the reference
Import store from '. / Redux / store' // note the location of the reference
function App() {
  return (
    <Provider store = {store}>
      <AddTodo />
      <ShowList />
      <Filter />
    </Provider>
  );
}
export default App;

Trigger automatic execution of reducer

In practice, the dispatch method needs to be triggeredreducerTo automatically execute thestateMake changes. For this reason,storeNeed to knowreducerFunction, the method is to generatestoreWhen, willreducerafferentcreateStoremethod.

// redux/store
import {createStore} from 'redux'
import reducers from './reducers/reducers'
//The createstore takes reducers as a parameter to generate a new store.
//In the future, whenever dispatch sends a new action, it will automatically call reducers (a combination of multiple reducers) to get a new state.
const store = createStore(reducers)
export default store

Add items

UI component addtodo

newly buildAddTodoComponent. When you click add, the value in the box will be enteredvalueBy callingpropsReceivedaddTodoTextMethod, pass tocontainersContainer components underaddtodoMedium.

//components/addtodo/AddTodo
import React, { Component } from 'react';
class AddTodo extends Component {
  handleAdd() {
    if(this.refs.inputText.value) {
      this.props.addTodoText(this.refs.inputText.value)
      //Call the received addtodotext method
      //This method will connect with the component addtodo in the container component addtodo under containers
      this.refs.inputText.value = ''
    }
  }
  render() { 
    return ( 
      <div>
        <input type="text" ref="inputText" />
        <button onClick={ this.handleAdd.bind (this)} > Add < / button >
      </div>
    );
  }
}
export default AddTodo;

Container component addtodo

connectMethod will change the UI componentAddTodoWrap and add business logic: input logicmapStateToPropsLogic outputmapDispatchToPropsFinally, we get a container componentaddtodo。 Only the output logic is used here (how the user’s operation on the component becomes an action object, and the click “add item” will be passed out from here).

// containers/addtodo
import AddTodo from '../components/addtodo/AddTodo';
import { connect } from 'react-redux'
import { addTodo } from '../redux/actions'
//This is a key point, we must understand
const mapDispatchToProps = (dispatch) => {
  return {
    addTodoText: (text)=> {
      // console.log ('transfer succeeded ', text);
      dispatch(addTodo(text))
      //Dispatch will issue action addtodo
      //Multiple actions are stored under Redux / actions
    }
  }
}
export default connect(null, mapDispatchToProps)(AddTodo)
// redux/actions
import * as actionTypes from './actionTypes'
export function addTodo(text) {
  return { type: actionTypes.ADD, text, completed: false}
  //Under actiontypes, several parameters are stored to describe the modification intention
}
//   redux/actionTypes
export const ADD = "ADD"
//Add event

Trigger reducer

In container componentsaddtodoTriggered indispatchAnd pass on a new oneaction, auto callreducersMediumtodolist

// reducers/todolist
 function NewList(state = [], action) {
 //The state content of the call is the content after the last addition
 //New content in action
  switch(action.type){
    case 'ADD': 
      state = [{text: action.text, completed: action.completed}, ...state] 
      return state
    default: return state
  }
}
export default NewList
// reducers/reducers
import { combineReducers } from 'redux'
import NewList from './todolist'
export default combineReducers({
  NewList,
  //There are several reducers to be introduced here
})

Get the data after the reducer processing

The UI component will be used hereShowListContainer components forshowlistshowlistThrough input logic mapStateToPropsobtainreducerAfter processingstateAnd map it to the UI componentShowListOfpropsMedium.

//  containers/showlist
//Only container components can get state
import { connect } from 'react-redux';
import ShowList from '../components/showlist/ShowList';
const mapStateToProps = (state) => {
  return {
    list: state.NewList
  }
}
export default connect (mapStateToProps, null)(ShowList)

Component showlist rendering data

stateThrough the transmission of container components, thethis.propsIn the.

import React, { Component } from 'react';
class ShowList extends Component {
  render() {
    let { list } =  this.props  //Finally get the item after clicking Add
    return (
      <ul>
        {
          list.map((item, index) => (
            <li key={index}>
              {item.text}
            </li>
          ))
        }
      </ul>
    );
  }
}
export default ShowList;

Completion

Implementation: click on the item, the deletion line appears, indicating that it has been completed

UI component showlist

Add a click event for each item, and click the itemidPassed to the container assemblydispatchTo triggerreducerMake changes.

class ShowList extends Component {
  handleDone(index) {
    return () => {
      this.props.completedThing(index)
    }
  }
  render() {
    let { list } = this.props
    return (
      <ul>
        {
          list.map((item, index) => (
            <li onClick={this.handleDone(index)} key={index}
              className={item.completed ? 'line-through' : ''}
              ref='node'>
                 //Changing styles in CSS files
              {item.text}
            </li>    
          ))
        }
      </ul>
    );
  }
}
export default ShowList;

Container component showlist

Through the trigger of UI components, themapDispatchToPropsInitiated indispatchRequest (similar to adding items).

// containers/showlist
import { connect } from 'react-redux';
import ShowList from '../components/showlist/ShowList';
import { completed } from '../redux/actions'   
//Introduce action
const mapStateToProps = (state) => {
  return {list:  state.NewList }// previously written
}
const mapDispatchToProps=(dispatch)=>{
  return {
    completedThing:(index)=>{
      // console.log ('transfer succeeded ', index);
      dispatch(completed(index))
      }
  }
}
export default connect (mapStateToProps, mapDispatchToProps)(ShowList)
// actions
export function completed(index) {
  return { type: actionTypes.DONE, index}
  //Pass the ID of the item to reduce
}

// actionTypes
//Complete the event
export const DONE = 'DONE'

Trigger reducer

Call againreducersMediumtodolist

//  reducers/todolist 
function NewList(state = [], action) {
  ......
    case 'DONE':
      return (() => {
        state = state.slice(0)
        state[action.index].completed = !state[action.index].completed; 
        //Modify the complete parameter in the item and return the data
        return state
      })()
    default: return state
  }
}
export default NewList

Get and render

Modifiedstate, UI componentShowListIt will be re rendered and the relevant method will not be changed.

Screening items

UI component filter

Add the click events of three buttons corresponding to the methods on the container component.

// components/filter/Filter
import React, { Component } from 'react';
class Filter extends Component {
  handleAll() {
   this.props.renderAll()
  }
  handleActive() {
    this.props.renderActive()
  }
  handleGone() {
    this.props.renderGone()
  }
  render() { 
    return ( 
      <div>
        <button onClick={ this.handleAll.bind (this)} > all
        <button onClick={ this.handleActive.bind (this)} > incomplete
        <button onClick={ this.handleGone.bind (this)} > completed < / button >
      </div>
    );
  }
}
export default Filter;

Container component filter

Through the trigger of UI components, themapDispatchToPropsInitiated indispatchRequest.

import { connect } from 'react-redux';
import Filter from '../components/filter/Filter';
import { selectAll, selectActive, selectGone } from '../redux/actions'

const mapDispatchToProps = (dispatch) => {
  return {
    renderAll: () => {
      // console.log ('load all ');
      dispatch(selectAll())
    },
    renderActive: () => {
      // console.log ('loading not completed ');
      dispatch(selectActive())
    },
    renderGone: () => {
      // console.log ('loading completed');
      dispatch(selectGone())
    }
  }
}
export default connect(null, mapDispatchToProps)(Filter)
// actions
export function selectAll() {
  return { type: actionTypes.ALL }
  //Note that the button parameter "all" is passed here
}
export function selectActive() {
  return { type: actionTypes.ACTIVE }
}
export function selectGone() {
  return { type: actionTypes.GONE }
}

// actionTypes
//Load all events
export const ALL = 'ALL'
//Loading incomplete events
export const ACTIVE = 'ACTIVE'
//Loading event completed
export const GONE = 'GONE'

Trigger reducer

callreducersUnder thefilter, return the corresponding parameter in theFilterTtpeMedium.

// reducers/filter
function FilterType(state, action) {
  switch(action.type) {
    case 'ACTIVE':
      return 'ACTIVE'
    case 'GONE':
      return 'GONE'
    default:
      return 'ALL'
      //By default, click all to load all items
  }
}
export default FilterType

Get and render

In container componentsshowlistThrough the receivedNewListandFilterType, yeslistFilter and return to the UI component after filtering the new table. UI componentsShowListRe render.Because no new items are added during the process of clicking the filter button, thestateinNewListIt’s always the last time you add it.

import { connect } from 'react-redux';
import ShowList from '../components/showlist/ShowList';
import { completed } from '../redux/actions'

const mapStateToProps = (state) => {
  //console.log(state.NewList);
  let fileList = []
  switch(state.FilterType) {
    case 'ACTIVE':
      fileList = state.NewList.filter(item => item.completed === false)
      return { list: fileList}
    case 'GONE':
      fileList = state.NewList.filter(item => item.completed === true)
      return { list: fileList}
    default:
      return { list: state.NewList}
  }
}
const mapDispatchToProps=(dispatch)=>{
  return {
    completedThing:(index)=>{
      // console.log ('transfer succeeded ', index);
      dispatch(completed(index))
      }
  }
}
export default connect (mapStateToProps, mapDispatchToProps)(ShowList)

summary

  • componentsThe UI components under the folder are only responsible for rendering data, not for business logic; all parameters are controlled bythis.propsProvided, not usedthis.state
  • containersThe container component under the folder is responsible for data management and business logicmapStateToProps, mapDispatchToPropsTo obtain or process data.
  • react-reduxProvidedconnectMethod is used to generate container components.
  • mapStateToPropsResponsible for input logic, willreducerReturnedstateMapping to UI componentspropsMedium.
  • mapDispatchToPropsResponsible for the output logic, mapping the user’s feedback parameters in theactionAnd through the launchdispatchTo pass on toreducerMake changes.

Recommended Today

Regular expression sharing for checking primes

This regular expression is shown as follows: Regular expressions for checking prime numbers or not To use this positive regular expression, you need to convert the natural number into multiple 1 strings. For example, 2 should be written as “11”, 3 should be written as “111”, 17 should be written as “11111111111”. This kind of […]