10_Redux的应用(数据共享及简化代码)

前言

经过react-redux的学习已经了解了store基础操作,但是在实际开发过程中是多个组件之间进行数据共享。action、reducer、store是redux操作的核心。一般我们在constant里对type变量进行封装,action、reducer都需要它。

  • UI组件:在这里我们先进行组件渲染,把可能发生的动作记录下来。
  • 容器组件:负责和redux通信和状态更新,为了简化操作,可将UI组件整合到容器组件中,最后暴露容器组件即可。容器组件又是通过connect与UI组件建立连接,所有容器组件为父组件,UI组件获得容器组件传来的数据通过props即可
  • action: 根据type,找到reducer里的具体数据操作
  • reducer: 用于初始化和加工状态。reducer为纯函数
  • store对象:整个应用只要一个store对象,所以直接在入口文件 index.js通过 provider将store传递给整个应用。
import store from "./redux/store"
 <Provider store={store}>
      <App />
    </Provider>

一、多组件数据共享

1.1 容器组件

1.1 Count容器组件

import React, { Component } from "react"
import "./index.css"
  •  Count
import React, { Component } from "react"
import "./index.css"

//引入connect用于连接UI组件和redux store
import { connect } from "react-redux"

class CountUI extends Component {
  addNum = () => {
    // const { value } = this.selectNumber
  }
  //减法
  subNum = () => {
    // const { value } = this.selectNumber
  }
  //奇数加
  addNumIfodd = () => {}
  //异步加
  addNumAsync = () => {
    // const { value } = this.selectNumber
  }
  render() {
    return (
      <div>
        <h3>
          Count组件
          <span style={{ marginLeft: "30px" }}>person总人数:</span>
        </h3>

        <h3>
          当前求和为:<span></span>
        </h3>
        <select
          name="select"
          id=""
          ref={(c) => (this.selectNumber = c)}
        >
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>

        <button onClick={this.addNum}>+</button>
        <button onClick={this.subNum}>-</button>
        <button onClick={this.addNumIfodd}>当前求和为奇数加</button>
        <button onClick={this.addNumAsync}>异步加</button>
      </div>
    )
  }
}

export default connect()(CountUI)

1.2 Person容器组件

  • Person
import React, { Component } from "react"
import { nanoid } from "nanoid"
import "./index.css"
import { connect } from "react-redux"

class PersonUI extends Component {
  addPerson = () => {
    const name = this.nameNode.value
    const age = this.ageNode.value

    const perobj = { id: nanoid(), name, age }
    console.log(perobj)
    // this.nameNode.value = ""
    // this.ageNode.value = ""
  }
  render() {

    return (
      <div>
        <h3>
          Person组件
          <span style={{ marginLeft: "30px" }}>count组件的和:</span>
        </h3>
        <input
          ref={(c) => (this.nameNode = c)}
          type="text"
          placeholder="输入名字"
        />
        <input
          ref={(c) => (this.ageNode = c)}
          type="text"
          placeholder="输入年龄"
        />
        <button onClick={this.addPerson}>添加</button>
        <ul>
          <li>----姓名:----年龄:</li>
        </ul>
      </div>
    )
  }
}

export default connect()(PersonUI)

1.2 constant.js

该模块式用于定义type类型的常量值。Count容器组件,add和sub;Person容器组件addperson

export const ADD = "add"
export const SUB = "sub"
export const ADDPERSON = "addperson"

1.3  redux

1.3.1 actions

  • count.js
import { ADD, SUB } from "../constant"
export const add = (data) => ({
  type: ADD,
  data,
})
export const sub = (data) => ({
  type: SUB,
  data,
})
  1.  异步Action,也就是返回值为函数,且能开启异步任务
  2. 异步Action一般都会调用同步Action
  3. 异步Action不是必须要用的
export const addAsync = (data, time) => {
  return (dispatch) => {
    //异步任务
    setTimeout(() => {
      dispatch(add(data))
    }, time)
  }
}
  • person.js
import { ADDPERSON } from "../constant"
export const addPerson = (perobj) => ({
  type: ADDPERSON,
  data: perobj,
})

1.3.2 reducers

  • count.js
import { ADD, SUB } from "../constant"
const initState = 0

export default function countReducer(preState = initState, action) {
  const { type, data } = action
  //根据type决定如何加工数据
  switch (type) {
    case ADD:
      return preState + data
    case SUB:
      return preState - data
    default:
      return preState
  }
}
  • person.js
import { ADDPERSON } from "../constant"
//初始化列表
const initState = [{ id: "001", name: "Tom", age: 18 }]

export default function personReducer(preState = initState, action) {
  const { type, data } = action
  switch (type) {
    case ADDPERSON:
      return [data, ...preState]
    default:
      return preState
  }
}

redux的reducer函数必须是一个纯函数

什么是纯函数?

1) 不得改写参数数据

2)  不会产生任何副作用,例如网络请求,输入和输出设备

3)  不能调用Date.now()或者Math.random()等不纯的方法

  • index.js

该文件用于汇总reducer,combineReducers传入的对象,就是reducer里保存的总状态对象

import count from "./count"
import persons from "./person"
import { combineReducers } from "@reduxjs/toolkit"
export default combineReducers({
  count,
  persons,
})

1.4 store

import { configureStore } from "@reduxjs/toolkit"
//引入汇总后的reducer
import reducer from "./reducers/index"
export default configureStore({
  reducer,
})

至此,store的初始加工完成,接下来要在容器组件中对数据进行加工

1.5 加工数据

connect(映射状态)(映射操作状态的方法)(关联组件)

  • Count容器

state.count和 state.persons 是store定义的,react-redux会帮我们自动dispatch所属的action。然后根据action的type找到对应的数据处理逻辑,,并把action携带的数据带走。因为又是所属容器,UI组件调用需要通过props。

export default connect(
  // state总状态
  (state) => ({ count: state.count, perlen: state.persons.length }),
  // mapDispatchToProps简写  react-dedux帮自动分发
  {
    add,
    sub,
    addAsync,
  }
)(CountUI)
addNum = () => {
    const { value } = this.selectNumber
    this.props.add(value * 1)
  }
  //减法
  subNum = () => {
    const { value } = this.selectNumber
    this.props.sub(value * 1)
  }
  //奇数加
  addNumIfodd = () => {
    //如何获取count
    const { count } = this.props
    if (count % 2 !== 0) {
      this.addNum()
    }
  }
  //异步加
  addNumAsync = () => {
    const { value } = this.selectNumber
    this.props.addAsync(value * 1, 500)
  }

Count组件和、Person组件人数和通过props获取

 const { count, perlen } = this.props
  • Person容器
import { nanoid } from "nanoid"
export default connect((state) => ({ obj: state.persons, sum: state.count }), {
  addPerson,
})(PersonUI)
addPerson = () => {
    const name = this.nameNode.value
    const age = this.ageNode.value * 1
    // console.log(name, age)
    const perobj = { id: nanoid(), name, age }
    //console.log(perobj)
    this.props.addPerson(perobj)
    this.nameNode.value = ""
    this.ageNode.value = ""
  }

Count组件和

const { sum } = this.props

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

才不吃胡萝卜嘞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值