Redux学习之路----带你学会“全局状态树”

3 篇文章 0 订阅

🚀🚀首发:CSDN碰磕,学无止境


🌞🌞🌞晴29°


✊✊Better to light one candle than to curse the darkness.


📅2022/6/20


Redux学习

主要用作应用状态的管理-----“全局状态树🌳”

  • state以单一对象存储在store对象中
  • state只读(每次都返回一个新对象)
  • 使用纯函数reducer执行state更新

安装

npm i redux

使用

创建文件夹redux—>store.js

引入—>创建

/**
 * Redux
 */
//1、引入redux
//2.createStore(reducer)
import {createStore} from 'redux';

const reducer=(prevState={
    name:"学习"
},action)=>{
    console.log(action)
    return prevState;
}
const store=createStore(reducer);
export default store;

zhuye,js

通过store.subscribe()订阅

  • store.getState()拿到传来的数据
 //store.subscribe订阅
  componentDidMount(){
    store.subscribe(()=>{
      console.log("app中订阅",store.getState())//store.getState()拿到最新状态..
    })
  }

NotFound.js

通过store.dispatch通知,参数为传的值

function NotFound(){
    useEffect(()=>{
        // console.log("进入404")
        //store.dispatch通知
        store.dispatch({
            type:"404传的消息",
            val:"碰磕"
        })
        return()=>{
            console.log("销毁...");
        }
    },[])
    return (
        <div>
            404
        </div>
    );
}

该代码只要一进入该页面就会通知store.js,退出则会打印销毁,再通过store.js进行数据处理然后再转发给订阅者zhuye.js,最后主要拿到想要的数据…进行相对应操作

这就是Redux的一个工作流程,完美解决了传参的复杂繁琐性…

Redux-reducer合并(reducer的拆分合并)

将reducer进行拆分最终合成一个大reducer

主要关键词:combineReducers

合并

创建两个不同的reducer

CityReducer.js

const CityReducer=(prevState={
    cityName:"江西"
},action)=>{
    console.log(action)
    let newState={...prevState}
    switch(action.type){
        case "change-city":
            newState.cityName=action.citys
            return newState
        default:
            return prevState
    }
}
export default CityReducer;

TabbarReducer.js

const TabbarReducer=(prevState={
    name:"学习"
},action)=>{
    console.log(action)
    let newState={...prevState}
    switch(action.type){
        case "404传的消息":
            newState.cityName=action.citys
            return newState
        default:
            return prevState
    }
}
export default TabbarReducer;

redux中:store.js

引入两个reducer再通过combineReducers进行合并

/**
 * Redux
 */
//1、引入redux
//2.createStore(reducer)
import {combineReducers, createStore} from 'redux';
import CityReducer from './reducers/CityReducer';
import TabbarReducer from './reducers/TabbarReducer';
const reducer=combineReducers({
    CityReducer,
    TabbarReducer
})

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

访问

在没有拆分前:

store.getState().cityName

拆分后导致层级多了一级

store.getState().CityReducer.cityName

这样就成功了,这样做方便管理,方便共同开发互不影响.

redux-thunk(处理异步)

处理异步的中间件

安装

npm i redux-thunk

引入

通过applyMiddleware引用中间件

引入总redux中store.js

import reduxThunk from 'redux-thunk'
//引用中间件
const store=createStore(reducer,applyMiddleware(reduxThunk));//applyMiddleware引用中间件

使用

创建一个reducer----CinemaListReducer.js

用于接收通知消息

const CinemaListReducer=(prevState={
    list:[]
},action)=>{
    console.log(action)
    let newState={...prevState}
    switch(action.type){
        case "change-list":
            newState.list=action.list
            console.log(newState)
            return newState
        default:
            return prevState
    }
}
export default CinemaListReducer;

Cinemas.js

这里判断缓存是否有数据,有就直接拿,没有就请求后台数据,并且进行订阅消息,从而得到消息

请求是通过异步请求

import React, { useEffect, useState} from 'react';
import store from '../redux/store';
import {useNavigate} from 'react-router-dom';
import getCinemaListAction from '../redux/ActionCreator/getCinemaListAction';
function Cinemas(){
    const navigate = useNavigate()
    const [cityName,setcityName] =useState(store.getState().CityReducer.cityName)
    const [cinemaList,setCinemaList] =useState(store.getState().CinemaListReducer.list)
    useEffect(()=>{
        if(store.getState().CinemaListReducer.list.length==0){
            //说明数据为空,就请求后台数据
            // actionCreator里写异步
            store.dispatch(getCinemaListAction())
        }else{
            //拿缓存的数据
            console.log("拿数据")
        }
        //订阅
        store.subscribe(()=>{
            console.log("cinemas订阅拿到的数据:",store.getState().CinemaListReducer.list)
            setCinemaList(store.getState().CinemaListReducer.list)
        })
    },[])
    return (
        <div>
            Cinemas
            <p onClick={()=>{
                navigate('/city')
            }}>{cityName}</p>
            <ol>
                {
                    cinemaList.map(item=>{
                      return <li key={item.cinemaId}>{item.cinemaId}----{item.name}</li>
                    })
                }
            </ol>
        </div>
    );
}

export default Cinemas

调用getCinemaListAction进行异步请求

getCinemaListAction.js

格式是return一个函数

return(canshu)=>{

请求.then(res=>{

canshu({

​ 发布通知…传数据给CinemaListReducer,

})

})

}

import axios from 'axios'
function getCinemaListAction(){
    return(dispatch)=>{
    axios({
        method:'GET',
        url:"https://m.maizuo.com/gateway?cityId=440300&ticketFlag=1&k=2005318",
        headers:{
            "X-Client-Info": '{"a":"3000","ch":"1002","v":"5.2.0","e":"1654433035923688551579649"}',
            "X-Host": "mall.film-ticket.cinema.list"
        }    
    }).then(res=>{
        console.log(res.data.data.cinemas)
        dispatch({
            type:"change-list",
            list:res.data.data.cinemas
        })
    })
    }
}
export default getCinemaListAction;

这样Cinemas的页面就拿到数据了,并且第一次会调用函数请求,第二次就直接从缓存里就能拿,大大的提高了用户体验以及网页加载效率

缺陷:每次都会进行订阅…

取消订阅

订阅会有返回值,拿变量接收,执行改变量即可取消订阅…

//订阅
        let fh=store.subscribe(()=>{
            console.log("cinemas订阅拿到的数据:",store.getState().CinemaListReducer.list)
            setCinemaList(store.getState().CinemaListReducer.list)
        })
        return ()=>{
            //取消订阅
            fh();
        }

redux-promise(处理异步)

方案二…

安装

npm i redux-promise

引入

可以将两种方式都引入

引入总redux中store.js

import reduxThunk from 'redux-thunk'
import reduxPromise from 'redux-promise'
//引用中间件
const store=createStore(reducer,applyMiddleware(reduxThunk,reduxPromise));//applyMiddleware引用中间件


使用

两种写法都注释好了…

修改getCinemaListAction.js

import axios from 'axios'
// redux-thunk风格
/*
function getCinemaListAction(){
    return(dispatch)=>{
    axios({
        method:'GET',
        url:"https://m.maizuo.com/gateway?cityId=440300&ticketFlag=1&k=2005318",
        headers:{
            "X-Client-Info": '{"a":"3000","ch":"1002","v":"5.2.0","e":"1654433035923688551579649"}',
            "X-Host": "mall.film-ticket.cinema.list"
        }    
    }).then(res=>{
        console.log(res.data.data.cinemas)
        dispatch({
            type:"change-list",
            list:res.data.data.cinemas
        })
    })
    }
}*/
//redux-promise
function getCinemaListAction(){
    return axios({
        method:'GET',
        url:"https://m.maizuo.com/gateway?cityId=440300&ticketFlag=1&k=2005318",
        headers:{
            "X-Client-Info": '{"a":"3000","ch":"1002","v":"5.2.0","e":"1654433035923688551579649"}',
            "X-Host": "mall.film-ticket.cinema.list"
        }    
    }).then(res=>{
        console.log(res.data.data.cinemas)
        return {
            type:"change-list",
            list:res.data.data.cinemas
        }
    })
    
}
export default getCinemaListAction;

两种方式都可以使用,自己喜欢用哪个就用哪个~

redux开发者工具(浏览器插件)

可以在谷歌浏览器商店搜索:redux devTools进行添加拓展程序

官网地址:[GitHub - zalmoxisus/redux-devtools-extension: Redux DevTools extension.](GitHub - zalmoxisus/redux-devtools-extension: Redux DevTools extension.)

可参照官网配置,这里演示配置一下

只需要在store.js中改变一句代码

const store=createStore(reducer,applyMiddleware(reduxThunk,reduxPromise));//applyMiddleware引用中间件

将上方这句改成

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer,composeEnhancers(applyMiddleware(reduxThunk,reduxPromise)))

并且需要引入compose

import {compose} from 'redux';

这样就ok了,然后打开你的谷歌浏览器使用这个扩展程序即可!

大功告成!!!redux完结,下一篇文章再将redux与react进行整合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

碰磕

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

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

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

打赏作者

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

抵扣说明:

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

余额充值