Redux学习
🚀🚀首发: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
进行整合