Redux拓展

除了redux之外,还有两种中间件(Redux-thunk和Redux-saga)和常用组件(React-Redux),虽然用redux可以解决遇到的问题,但是学习这几种会使开发事半功倍

一、Redux-thunk

Redux-thunk 是Redux最常用的插件。什么时候会用到这个插件呢?比如在Dispatch一个Action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware(中间件)。在实际工作中你可以使用中间件来进行日志记录、创建崩溃报告,调用异步接口或者路由。 这个中间件可以使用是Redux-thunk来进行增强(当然你也可以使用其它的),它就是对Redux中dispatch的加强。

(一)安装

npm install --save redux-thunk

(二)案例——计数器【异步累加】

1、在index.js中

// 引入createStore对象
import {
    
     createStore ,applyMiddleware,compose} from 'redux'
// 引入中间件redux-thunk
import thunk from "redux-thunk"

// 引入reducer
import reducer from './reducer'

// 利用compose创造一个增强函数
const composeEnhancers =   window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
    
    }):compose

// 通过增强函数,把thunk引入进来
const enhancer = composeEnhancers(applyMiddleware(thunk))

// const store = createStore(
//     reducer,
//     window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
// );
const store = createStore(reducer,enhancer)
export default store;

2、统一管理action中的type,actionTypes.js

export const ASYNC_ADD_NUM_FN = "asyncAddNumFn";
export const JIAN = "jian";

3、统一管理action,actionCreator.js

import {
    
     ADD, JIAN, DEL_LIST_ITEM } from './actionTypes'
// 以异步累加举例
//export const asyncAddNumFn = (data) => {
    
    
//    return {
    
    
 //       type: 'ASYNC_ADD_NUM_FN', 
 //       value: data
 //   }
//}
// 以高阶函数的形式书写
export const asyncAddNumFn = (data) => {
    
    
    return (dispatch) => {
    
     
        setTimeout(() => dispatch({
    
     type: ASYNC_ADD_NUM_FN, value: data }), 2000)
    }
}
// 计数器的减法
export  const jianFnAction = () =>{
    
    
    return {
    
    
        type:JIAN
    }
}

4、在reducer.js中

import {
    
     JIAN,ASYNC_ADD_NUM_FN } from './actionTypes'

const initState={
    
    
    num:0
}
// 导出一个函数,用于返回state
export default (state = initState, action) => {
    
    
    let newState = JSON.parse(JSON.stringify(state));    // 对原本的state做一次深拷贝
    console.log(action);
    switch(action.type){
    
    
        case JIAN:
            newState.num -=1;
            return newState;
        case ASYNC_ADD_NUM_FN:
            newState.num +=action.value;
            return newState;
        default:
            break;
    }
    return newState;
}

5、页面中

import React, {
    
     Component } from 'react'
import store from '../redux';
import {
    
     addFnAction, jianFnAction,asyncAddNumFn} from '../redux/actionCreator'

export default class Count1 extends Component {
    
    
    state = {
    
    
        num:0
    }
constructor(p){
    
    
    super(p)
    this.state={
    
    
        num:0
    }
    this.state = store.getState()

    store.subscribe(this.storeChange.bind(this))
    console.log("11",this.state);
}
storeChange(){
    
    
    this.setState(
        store.getState()
     )
}
    render() {
    
    
        return (
            <div>
                <Add/>
                {
    
    this.state.num}
                <Jian/>
            </div>
        )
    }
}

// 子组件1加
class Add extends Component {
    
    
    add=()=>{
    
    
        // console.log("jia ");
        // store.dispatch(addFnAction())
       // redux-thunk会自动注入dispatch给actionCreators
  store.dispatch(asyncAddNumFn(1))
    }
    render() {
    
    
        return (
            <div onClick={
    
    this.add.bind(this)}>1</div>
        )
    }
}

// 子组件2减
class Jian extends Component {
    
    
    jian=()=>{
    
    
        console.log("jian");
        store.dispatch(jianFnAction())
    }
    render() {
    
    
        return (
            <div onClick={
    
    this.jian.bind(this)}>1</div>
        )
    }
}

运行之后会发现其效果了,加法是异步执行的。

6、特别说明

如果使用以下代码,在页面中派发事件的时候就会比较麻烦,需要套一个promise

export const asyncAddNumFn = (data) => {
    
    
     return {
    
    
         type: ASYNC_ADD_NUM_FN, 
         value: data
     }
 }

因此将这个setTimeout转移到actionCreator中,见上面第3点

二、Redux-saga

redux-saga 是 redux 一个中间件,用于解决异步问题。redux-saga基于ES6的Generator, github地址.

Saga的 redux-saga/effects 中有几个关键字:
fork:创建一个新的进程或者线程,并发发送请求。
call:发送 api 请求
put:发送对应的 dispatch,触发对应的 action
takeEvery:监听对应的 action,每一次 dispatch 都会触发
takeLatest:监听对应的 action,只会触发最后一次 dispatch
all:跟 fork 一样,同时并发多个 action,没有顺序。

由于redux-thunk与redux-saga两者作用大致相同,但redux-saga需要基于generator,写起来也较为复杂,这里只做个概念普及,有兴趣的可以自行查阅文档学习。

三、React-Redux

React-Redux 这是一个React生态中常用组件,它可以简化 Redux 流程,其实就是简化版的 Redux

(一)安装

npm install --save react-redux
npm install --save redux

(二)提供器与连接器

1、Provider提供器

是一个提供器,只要使用了这个组件,组件里边的其它所有组件都可以使用 store 了,这也是React-redux的核心组件了。简单的说:凡是放在 中的组件,都可以获取到store中的数据一般来说,提供器直接写在根组件

2、connect连接器

需要在组件中使用连接器和react相连,获取数据

(三)案例——计数器

1、在index.js中

// 引入createStore对象
import {
    
     createStore} from 'redux'
// 引入reducer
import reducer from './reducer'

const store = createStore(reducer);
export default store;

2、在reducer.js中

const initState={
    
    
    num:0
}
// 导出一个函数,用于返回state
export default (state = initState, action) => {
    
    
    let newState = JSON.parse(JSON.stringify(state));    // 对原本的state做一次深拷贝
    switch(action.type){
    
    
        case "add_count":
            newState.num +=action.value;
            return newState;
        default:
            break;
    }
    return newState;
}

3、入口函数中 index.js

使用提供器包裹,并提供store

import React from 'react';
import ReactDOM from 'react-dom/client';
import ReactRedux from './view/ReactRedux'
import {
    
     Provider } from 'react-redux'
import store from './redux/index'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={
    
    store}>
       <ReactRedux />
    </Provider>
  </React.StrictMode>
);

4、页面

通过connect链接,引入了两种映射, 做到了删除了store的引入,增加了连接器与映射关系

import React from 'react'
import {
    
    connect} from 'react-redux'  //引入连接器

function ReactRedux(props) {
    
    
  return (
    <div>
        <h2>{
    
    props.num}</h2>
        <button onClick={
    
    props.addFn}>增加</button>
    </div>
  )
}
// stateToProps是一种映射关系,把原来的state映射成组件中的props属性
const stateToProps = (state)=>{
    
    
    return {
    
    
        num : state.num
    }
}
// dispatchToPros也是一种映射,用于传递并修改数据,这里要返回一个对象并包含一个事件
const dispatchToPros = (dispatch)=>{
    
    
    return {
    
    
        addFn(){
    
    
            dispatch({
    
    
                type:"add_count",
                value:1
            })
        }
    }
}
export default connect(stateToProps,dispatchToPros)(ReactRedux);

(四)redux 和 react-redux的区别

1、概念

redux是react中进行state状态管理的JS库(并不是react插件),一般是管理多个组件中共享数据状态。这个是和Vuex是一样的。
React-Redux是Redux的官方React绑定库。它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。

2、使用

redux和组件进行对接的时候是直接在组件中进行创建。在这里插入图片描述

react-redux是运用Provider将组件和store对接,使在Provider里的所有组件都能共享store里的数据,还要使用connect将组件和react连接。
在这里插入图片描述
在这里插入图片描述

3、获取state的方式不一样

redux获取state是直接通过store.getState()。
在这里插入图片描述
react-redux获取state是通过mapStateToProps函数,只要state数据变化就能获取最新数据
在这里插入图片描述

4、触发action的方式不一样

redux是使用dispatch直接触发,来操作store的数据。
在这里插入图片描述

react-redux是使用mapDispathToProps函数然后在调用dispatch进行触发
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_55173487/article/details/128853711