Chapter 35 Multiple component status data sharing

Previously, our summation case was just a component, which was played by ourselves. Next, we used multiple components to achieve data exchange between them through redux.

Step 1: Change project directory structure

src
|--containers
|	|--Count
|--redux
|	|--actions
|		|--count.js
|	|--reducers
|		|--count.js
|	|--constant.js
|	|--store.js
|--App.jsx
|--index.js

Since we now want to share the status of multiple components, we need to divide the files into more detailed categories so that we can better maintain the project.

  • futuristiccount_action.js=become=> redux/actions/count.js
  • futuristiccount_reducer.js=become=>redux/reducers/count.js
  • The corresponding import paths of other files must also be modified accordingly, so I won’t go into details here.

Step 2: Create a new Person component

document:src/containers/Person/index.jsx

import React, {
    
     Component } from 'react'
import {
    
    nanoid} from 'nanoid'

export default class Person extends Component {
    
    

  addPerson = () => {
    
    
    const {
    
     nameNode, ageNode } = this
    const person = {
    
    
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    console.log(person)
  }

  render() {
    
    
    return (
      <div>
        <h1>Person组件,上方组件求和为:{
    
    this.props.sum}</h1>
        <input type="text" placeholder='请输入姓名' ref={
    
    c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={
    
    c => this.ageNode = c} />&nbsp;
        <button onClick={
    
    this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          <li>姓名1--年龄</li>
        </ul>
      </div>
    )
  }
}

Then introduce it into the App component

import React, {
    
     Component } from 'react'
// 引入Count的容器组件
import Count from './containers/Count'
import Person from './containers/Person'

export default class App extends Component {
    
    
  render() {
    
    
    return (
      <div>
        <Count/>
        <hr/>
        <Person/>
      </div>
    )
  }
}

The effect is as follows:

Insert image description here


Step 3: Write redux files related to Person component

(1). New constant type:ADD_PERSON

// src/redux/constant.js
// 该模块是用于定义action对象的type类型的常量值
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
export const ADD_PERSON = 'add_person'

(2). Add person’s action file

// src/redux/actions/person.js
import {
    
     ADD_PERSON } from '../constant'
// 添加人信息的action
export const createAddPersonAction = personObj => ({
    
    type: ADD_PERSON, data:personObj})

(3). Add person’s reducer file

// src/redux/reducers/person.js
import {
    
    ADD_PERSON} from '../constant'

const initData = [{
    
    id:'001',name:'tom',age:18}]
export default function personReducer (preState = initData, action) {
    
    
  // 获取type和data
  const {
    
    type,data} = action

  switch (type) {
    
    
    case ADD_PERSON:
      return [data,...preState]
  
    default:
      return preState
  }
}

(4). Container component integrated with Person

import React, {
    
     Component } from 'react'
import {
    
    nanoid} from 'nanoid'
import {
    
    connect} from 'react-redux'
import {
    
    createAddPersonAction} from '../../redux/actions/person'

class Person extends Component {
    
    

  addPerson = () => {
    
    
    const {
    
     nameNode, ageNode } = this
    const person = {
    
    
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    console.log(person)
  }

  render() {
    
    
    return (
      <div>
        <h1>Person组件</h1>
        <input type="text" placeholder='请输入姓名' ref={
    
    c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={
    
    c => this.ageNode = c} />&nbsp;
        <button onClick={
    
    this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          <li>姓名1--年龄</li>
        </ul>
      </div>
    )
  }
}

export default connect(
  state => ({
    
    peoList:state}), // 映射状态
  {
    
    } // 映射操作状态的方法
)(Person)

At this point, we have compiled the related code of the Person component, but it does not work now because our redux a>. ’s store does not use the logic in personreducer


Step 4: Rectify the store file content

// 引入createStore,专门用于创建redux中最为核心的store对象
import {
    
     createStore , applyMiddleware } from 'redux'
import countReducer from './reducers/count'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'

export default createStore(countReducer,applyMiddleware(thunk))


According to the code, we know that there is no Person related reducer introduced here, so how should we use it?

The answer is: introduce a new oneAPImerge multiplereducer===>combineReducers

combineReducers is a commonly used method of combining Reducer, which can make the code more concise and easier to maintain.

// 引入createStore,专门用于创建redux中最为核心的store对象
import {
    
     createStore , applyMiddleware, combineReducers } from 'redux'
import countReducer from './reducers/count'
import personReducer from './reducers/person'
// 引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'

const allReducer = combineReducers({
    
    
  sum: countReducer,
  peoples: personReducer
})
export default createStore(allReducer,applyMiddleware(thunk))

The above is the complete version of our modified store file. Here we use combineReducersthisAPI to < The /span>. this Passed to component were merged to form a new of the Count component and the PersonreducerallReducercreateStoreAPI


Step 5: Store data in redux in the Person component

import React, {
    
     Component } from 'react'
import {
    
    nanoid} from 'nanoid'
import {
    
    connect} from 'react-redux'
import {
    
    createAddPersonAction} from '../../redux/actions/person'

class Person extends Component {
    
    

  addPerson = () => {
    
    
    const {
    
     nameNode, ageNode } = this
    const person = {
    
    
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    // console.log(person)
    this.props.addPeople(person)
  }

  render() {
    
    
    return (
      <div>
        <h1>Person组件</h1>
        <input type="text" placeholder='请输入姓名' ref={
    
    c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={
    
    c => this.ageNode = c} />&nbsp;
        <button onClick={
    
    this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          {
    
    
            this.props.peoList.map((p)=>{
    
    
              return <li key={
    
    p.id}>{
    
    p.name}--{
    
    p.age}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

export default connect(
  state => ({
    
    peoList:state.peoples}), // 映射状态
  {
    
    addPeople:createAddPersonAction} // 映射操作状态的方法
)(Person)

View the effect:
Insert image description here


Step 6: The two components introduce each other into redux, which contains state data.

document:Person/index.jsx

import React, {
    
     Component } from 'react'
import {
    
    nanoid} from 'nanoid'
import {
    
    connect} from 'react-redux'
import {
    
    createAddPersonAction} from '../../redux/actions/person'

class Person extends Component {
    
    

  addPerson = () => {
    
    
    const {
    
     nameNode, ageNode } = this
    const person = {
    
    
      id: nanoid(),
      name: nameNode.value,
      age: ageNode.value * 1
    }
    // console.log(person)
    this.props.addPeople(person)
  }

  render() {
    
    
    return (
      <div>
        <h1>Person组件,上方组件求和为:{
    
    this.props.sum} </h1>
        <input type="text" placeholder='请输入姓名' ref={
    
    c => this.nameNode = c} />&nbsp;
        <input type="text" placeholder='请输入年龄' ref={
    
    c => this.ageNode = c} />&nbsp;
        <button onClick={
    
    this.addPerson}>添加</button>
        <h2>人员列表</h2>
        <ul>
          {
    
    
            this.props.peoList.map((p)=>{
    
    
              return <li key={
    
    p.id}>{
    
    p.name}--{
    
    p.age}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

export default connect(
  state => ({
    
    peoList:state.peoples,sum:state.sum}), // 映射状态
  {
    
    addPeople:createAddPersonAction} // 映射操作状态的方法
)(Person)

document:Count/index.jsx

// 引入action
import {
    
    
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/actions/count'

// 引入react-redux中的connect用于连接UI组件和容器组件
import {
    
     connect } from 'react-redux'
import React, {
    
     Component } from 'react'

class Count extends Component {
    
    

  increment = () => {
    
    
    // 普通加
    // 1、获取用户选择的值
    const {
    
     value } = this.selectNumber
    this.props.jia(value*1)
  }

  decrement = () => {
    
    
    // 普通减
    // 1、获取用户选择的值
    const {
    
     value } = this.selectNumber
    this.props.jian(value*1)
  }

  incrementIfOdd = () => {
    
    
    // 当前求和为奇数为
    // 1、获取用户选择的值
    const {
    
     value } = this.selectNumber
    if (this.props.count %2 !== 0) {
    
    
      this.props.jia(value*1)
    }
  }

  incrementAsync = () => {
    
    
    // 异步加
    // 1、获取用户选择的值
    const {
    
     value } = this.selectNumber
    this.props.jiaAsync(value*1,500)
  }

  render() {
    
    
    return (
      <div>
        <h1>当前求和为:{
    
    this.props.count},下方组件人数为{
    
    this.props.peoLens}</h1>
        <select ref={
    
    (c) => (this.selectNumber = c)}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        &nbsp;
        <button onClick={
    
    this.increment}>+</button>&nbsp;
        <button onClick={
    
    this.decrement}>-</button>&nbsp;
        <button onClick={
    
    this.incrementIfOdd}>当前求和为奇数为</button>&nbsp;
        <button onClick={
    
    this.incrementAsync}>异步加</button>&nbsp;
      </div>
    )
  }
}


// 创建并暴露一个容器组件
export default connect(
  state => ({
    
    count: state.sum, peoLens: state.peoples.length}),
  {
    
    
    jia:createIncrementAction,
    jian:createDecrementAction,
    jiaAsync:createIncrementAsyncAction
  }
  )(Count)

overall effect:

Insert image description here


Summarize

(1). Define a Person component and share data with the Count component throughredux

(2). >Regular amountPersonreduceractionconstant

(3). Key points: Person’s reducer and Count’s Reducer To use combineReducer for merging, the total state after merging is an object!

(4). What is handed over tostore is the totalreducer. Finally, pay attention to the corresponding status when the component is taken out. key and value should be "taken in place".

Guess you like

Origin blog.csdn.net/qq_36362721/article/details/130762159