react笔记:redux

redux状态管理

安装redux:num i redux

新建redux文件夹:

  • store.js
  • count_reducer.js
  • count_action.js
  • constant.js (常量)
1. store.js文件:
javascript 复制代码
// 该文件专门用于暴露一个store对象,整个应用只有一个store对象
// 引入createStore,专门用于创建redux中最为核心的store对象
import {createStore} from 'redux'
// 引入为count组件服务的reducer
import countReducer from './content_reducer'
//暴露创建的reducer
export default createStore(countReducer)
2.count_reducer.js文件:
javascript 复制代码
//1. 该文件用于撞见一个为count组件服务的reducer,reducer的本质就是一个函数
//2. reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象action
import {INCREMENT,DECREMENT}from './constant'
const initState=0
export default function countReducer(preState=initState,action){
    console.log(preState)
    const {type,data}=action
    switch (type){
        case INCREMENT:
            return preState+data
        case DECREMENT:
            return preState-data
        default:
            return preState
    }
}
3.count_action.js文件:
javascript 复制代码
// 该文件撞门为count组件生成action对象
import {INCREMENT,DECREMENT} from './constant'

export const createIncrementAction=data=>({type:INCREMENT,data})
export const createDecrementAction=data=>({type:DECREMENT,data})

这里是下面函数的箭头函数的简写:函数返回一个对象

javascript 复制代码
 export function createDecrementAction(data){
    return {type:DECREMENT,data}
}

写成箭头函数:函数调用后要返回一个对象,需要在对象外包一个括号的写法,就会返回一个对象,否则{}会默认当作函数体处理。-----如: ({type:INCREMENT,data})

4.constant.js文件
javascript 复制代码
// 该模块是用于定义action对象中type类型的常量值
export const INCREMENT='increment'
export const DECREMENT='decrement'
count组件中:
javascript 复制代码
import React, { Component } from 'react'
import store from '../../redux/store'
import {createIncrementAction,createDecrementAction} from '../../redux/count_action'
export default class index extends Component {
    componentDidMount(){
        // 检测redux中的状态的变化,只要变化,就调用render
        store.subscribe(()=>{
            this.setState({})
        })
    }
    // 加
    increment=()=>{
      const {value}=this.selectNumber
      store.dispatch(createIncrementAction(value*1))
    }
    // 减
    decrement=()=>{
        const {value}=this.selectNumber
        store.dispatch(createDecrementAction(value*1))
    }
    // 奇数加
    incrementIfOdd=()=>{
        const {value}=this.selectNumber
        const count=store.getState()
        if(count%2!==0){
            store.dispatch({type:'increment',data:value*1})
        }
    }
    // 异步加
    incrementAsync=()=>{
        const {value}=this.selectNumber
        setTimeout(() => {
            store.dispatch({type:'increment',data:value*1})
        }, 500);
    }

  render() {
    return (
      <div>
        <h1>当前求和为:{store.getState()}</h1>
        <select ref={c=>this.selectNumber=c}>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button onClick={this.increment}>+</button>
        <button onClick={this.decrement}>-</button>
        <button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
        <button onClick={this.incrementAsync}>异步加</button>
      </div>
    )
  }
}
关于redux和视图更新:

修改store中的数据并不会触发视图更新,要触发视图更新,可以通过在组件内部订阅store的方式更新组件state。

一般更省事的方法是通过在入口文件中包一层订阅:

原理是只要store数据有更新,就触发App组件更新,这里react有diff算法,所以应该对性能的损耗不是特别大,所以这种方法也会更省事一点。

异步任务:

如果以下的业务代码异步加需要放到redux中处理,不想在组件内操作,则需要用到异步action:

dispatch一个异步任务action,传入参数值加的值,和异步时间:store.dispatch(createIncrementAsyncAction(value*1,1000))

javascript 复制代码
   // 异步加
    incrementAsync=()=>{
        const {value}=this.selectNumber
        // setTimeout(() => {
        //     store.dispatch({type:'increment',data:value*1})
        // }, 500);
        // 异步任务:
        store.dispatch(createIncrementAsyncAction(value*1,1000))
    }

action中定义异步action:

javascript 复制代码
// 异步action,就是指action的值为函数,因为只有在函数内部才能开启定时器等异步操作
export const createIncrementAsyncAction=(data,time)=>{
    return()=>{
        setTimeout(() => {
            store.dispatch({INCREMENT, data})
        }, time);
    }
}

这里dispatch部分也可以写成,调用了上面定义的同步任务,返回一个对象:

javascript 复制代码
  store.dispatch(createIncrementAction(data))

到这里触发异步操作就会报错:

Actions must be plain objects. Instead, the actual type was: 'function'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions.

因为store不能识别异步任务,所以这里要使用异步任务的话还需要一个中间件:redux-thunk

安装: npm i redux-thunk

使用:在store.js文件中导入thunk和applyMiddleware

此时就能执行异步任务了......

最后。可以发现,其实异步action并不是必须的,可以在业务组件中获取数据后再去修改维护store,但是如果需要抽离到action中,就会使用到。

相关推荐
pe7er7 小时前
React Native 多环境配置全攻略:环境变量、iOS Scheme 和 Android Build Variant
前端·react native·react.js
知识分享小能手8 小时前
Vue3 学习教程,从入门到精通,Vue 3 + Tailwind CSS 全面知识点与案例详解(31)
前端·javascript·css·vue.js·学习·typescript·vue3
茴香豆的茴18 小时前
转码刷 LeetCode 笔记[2]:203. 移除链表元素(python)
笔记·leetcode·链表
wdfk_prog8 小时前
[Linux]学习笔记系列 -- [arm][lds]
linux·运维·arm开发·笔记·学习
无名咸鱼10 小时前
CICD部署流程详解文档笔记
笔记·ci/cd
柑橘乌云_10 小时前
vue中如何在父组件监听子组件的生命周期
前端·javascript·vue.js
秋风战士10 小时前
通信算法之306:精通FPGA-笔记核心
笔记·fpga开发
一颗正在价投韭菜11 小时前
《范仲淹传》读书笔记与摘要
笔记·学习·范仲淹
江湖人称小鱼哥11 小时前
react接口防抖处理
前端·javascript·react.js
GISer_Jing12 小时前
腾讯前端面试模拟详解
前端·javascript·面试