Redux(Redux-thunk)

React-Redux

知识点

  1. redux redux-thunk

  2. redux redux-saga

  3. mobx

简介

redux是什么?
Redux是js应用的 一种可预测的状态容器(状态管理工具)
为什么要使用redux?
因为react只是DOM的抽象层,它没有涉及到另外两个方面 ,不是一个完整的web应用解决方案
1. 代码结构
2. 组件之间的通信
redux出现的时间?
1. 2015年
2. 它是2013年出现的flux的升级版
3. redux将flux和函数式编程结合在一起了
redux什么时候使用?
1. 当你做这个项目的时候你就知道了
2. 前后端数据交互多、前端表单也很多
3. redux并不是必须使用的

核心概念

Redux的构成部分
  1. store

    用于存储state 管理state的地方

  2. actionCreators

    动作的创建者,用于创建action, 用于区别界面到底做了哪些动作

  3. reducers

    用于修改数据 reducers必须是纯函数

  4. View

    界面,在react中,其实就是组件

Redux的设计思想:
1. Web 应用是一个状态机,视图与状态是一一对应的。
2. 所有的状态,保存在一个对象里面(唯一数据源)
   1. Redux的数据是一个对象
Redux三大使用原则
1. 单一数据源(Single Source of Truth)
2. 状态是只读的(返回值必须是新对象,不能直接修改原state) State is read-only
3. 使用纯函数来执行修改数据(输入输出一致)
Redux的流程(Flow)
  1. 打造store

  2. 打造reducers给store初始值

  3. 将store中数据取出来给了组件

  4. 组件中触发动作激活actionCreators

    1.比如一个点击事件

    2.比如一个输入事件

    3.一个前后端交互

  5. actionCreators 创建action 发送reducers

  6. reducers中修改数据

流程图

redux

Redux 插件

  1. redux

    redux核心库

    $ yarn add redux
    
  2. redux-thunk

    用于实现异步数据请求的redux中间件

    $ yarn add redux-thunk
    
  3. redux-saga

    用于实现异步数据请求的redux中间件

    $ yarn add redux-saga
    
  4. react-redux

    用于实现redux的数据划分:例如 home/user/list…

    $ yarn add react-redux
    
  5. redux-devtools-extension

    用于激活chrome浏览器的redux调试插件

    $ yarn add redux-devtools-extension
    
  6. Redux-DevTools 浏览器调试工具

    浏览器插件:Redux-DevTools

    下载地址:https://chrome.zzzmh.cn/info?token=lmhkpmbekcpmknklioeibfkpmmfibljd

Redux-thunk 版本使用

1.打造store

src/stroe/index.ts 或者 src/models/index.ts

const store=createStore(reducer,enhancer)

reducer 为修改数据的纯函数,为rootReducer(整个项目)

​ rootReducer为整个项目的集中管理者,下有很多reducers

enhancer 中间件(中间件就是具有特定功能的封装函数)

applyMiddleware 为中间件的执行函数

​ 底层原理:函数柯里化

import thunk from “redux-thunk”;

import { composeWithDevTools } from “redux-devtools-composeWithDevTools”;

import { createStore,applyMiddleware } from 'redux';
import rootReducer from './rootReducer';
import thunk from 'redux-thunk' // todo 用于实现异步数据请求
import { composeWithDevTools } from 'redux-devtools-extension'

const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)))

export default store ;

2.打造rootReducer

src/store/rootReducer.ts

//todo 打造rootReducer 
import { combineReducers } from 'redux'

const rootReducer = combineReducers({
    // 其他划分的reducer  count   /   todo  / list 
})

export default rootReducer

3.通过跨组件通信来进行数据通信(store数据给组件)

src/index.tsx

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

import "antd/dist/antd.css";
import {
  // HashRouter,//todo 表示选择hash模式
  BrowserRouter, // todo 表示选择history模式
} from "react-router-dom";

//add 导入store和跨组件通信组件
import store from "./store";
import { Provider } from "react-redux";

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
        {/* add 使用Provider组件包裹App组件*/}
      <Provider store={store}>
        <App />
      </Provider>
    </BrowserRouter>
  </React.StrictMode>,

  document.getElementById("root")
);

4.打造计数案例的count reducers

src/reducer/count.ts

reducer必须是一个纯函数(注意输入和输出保持一致)

输入 给参数previousState时state必须在对象{}中,这叫唯一数据源

输出 return必须是对象,redux的state是只读的,不能直接操作previousState,需要进行拷贝

拷贝方式

//浅拷贝 --只能拷贝一层
 const state=Object.create(previousState)
 const state=Object.assign({},previousState)
 const state={...previousState}
 const state=_.clone(previousState) //使用lodash
//深拷贝 --可以拷贝多层
  // 使用lodash方式
   const state=_.cloneDeep(previousState) 
  // immutable.js方式
   import {Map} from 'immutable'
   const initState=Map({n:1})
   const state=previousState 
  // json序列化方式
   const state=JSON.parse(JSON.stringify(previousState))


const initState={
    n:1
}
const countRdeucer=(previousState=initState,action={}) => {
    // previousState就是先前的state
    // action就是actionCreator发过来的action
    return {...previousState};
}

export default countRdeucer

5.在rootReducer中导入使用countReducer

src/store/rootReducer.ts

使用格式: 区块名称:导入的区块

import { combineReducers } from "redux";
import count from "../reducer/count";

const rootReducer =combineReducers({
   // 内容为其他划分的reducers
   count:count
})

export default rootReducer

6.用connect高阶组件从store中将数据取出给到组件

高阶组件

1.高阶组件就是一个函数,接收一个组件作为参数,返回一个新组件

2.功能:复用逻辑

connect函数是一个高阶组件

  1. 使用了connect,该组件就会用于store的数据和方法
  1. connect(arg1,arg2)(组件)

1.arg1是一个callback,用于获取store中的数据,然后以props形式给该组件

2.arg2是一个callback, 用于获取actionCretaor中的方法,然后以props形式给该组件

  1. 作用就是将store中的数据,actionCreators中的方法,以props属性的形式给到该组件,该组件就不需要定义数据和方法

bindActionCreators函数用于绑定action

//src /pages/Await.tsx
import React, { ReactElement, useState } from "react";
import { FC } from "react";
import countAction from "../../actions/count";
// 绑定action的
import { bindActionCreators } from "redux";

import { connect } from "react-redux";

interface Props {
    n:number;
    increment:(val:string)=>any;
    decrement:(val:string)=>any;

}
interface IcountState {n: number}

const Await: FC<Props> = ({n,increment,decrement}) => {
    const [val,setVal]=useState<string>('')
    const getVal=(e:any)=>{setVal(e.target.value)}
  return <div>
      {/* 受控组件 */}
      <input type="text" placeholder="请输入操作的数据" value={val} onChange={getVal}/>
      <button onClick={()=>{increment(val)}}> + </button>
      <button onClick={()=>{decrement(val)}}> - </button>
      <p>{n}</p>
  </div>;
};

export default connect(
  ({count}:{count:IcountState}) => {
      return count
  },
  (dispatch) => {
      return bindActionCreators(countAction,dispatch)
  }
)(Await);

8.打造公共常量

src/constant/index.ts

// todo count的相关常量
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'

9.打造actionCreator

src/actions/count.ts

打造属于count的actionCreators:

action的作用

创建action

通过return 发送action至对应的reducer

import * as type from './../constant/index';
// todo 打造属于count的actionCreators
// !! 没有异步数据请求时这样写
const countAction={
    increment(val:string){
        // count 递增方法
        const action={
            type:type.INCREMENT,
            payload:val
        }
        return action
    },
    decrement(val:string){
        // count 递减方法
        const action={
            type:type.DECREMENT,
            payload:val
        }
        return action
    }
}
export default countAction

10.reducer中的操作数据(修改逻辑)

src/reducer/count

逻辑:接收action发送过来的type,进行与常量的匹配,然后执行对应修改state的操作,并返回给store中的数据,store在将数据给组件

import * as constant from '../constant'
interface IAction {type: string;payload: string;}
const initState = {n: 1}
const countReducer = (previousState = initState,{ type, payload }: IAction) => {     
  switch ( type ) {
    case constant.INCREMENT:
      // 递增
      return {...previousState,n: previousState.n + Number(payload)}
    case constant.DECREMENT: 
      // 递减
      return {...previousState,n: previousState.n - Number(payload)}
    default:
      return {...previousState}
  }
}
export default countReducer 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值