redux
安装
npm install redux
一、单个reducer的使用
在src文件夹下面,新建一个store文件夹,里面新建一个store.js
import { legacy_createStore as createStore } from "redux"
const state = {
name: "zrs"
}
const reducer = (prevState = state, action = {}) => {
const newState = { ...prevState }
switch (action.type) {
case "change-name":
newState.name = "名字被改变了"
return newState
case "reset-name":
newState.name = "名字被重置了"
return newState
default:
return prevState
}
}
const store = createStore(reducer)
export default store
订阅
类组件中订阅
import React, { Component } from "react"
import store from "../store/store"
export default class PageA extends Component {
state = {
name: store.getState().name // 设置默认值为store里面的数据
}
componentDidMount() {
// 订阅
this.unsubscribe=store.subscribe(() => {
this.setState({ name: store.getState().name })
})
}
componentWillUnmount(){
// 解除订阅
this.unsubscribe()
}
render() {
return (
<>
<h1>{this.state.name}</h1>
</>
)
}
}
函数式组件中订阅
import React, { useState, useEffect } from "react"
import store from "../store/store"
const PageD = () => {
const [name, setname] = useState(store.getState().name) // 设置默认值为store里面的数据
useEffect(() => {
// 订阅
const unsubscribe = store.subscribe(() => {
setname(store.getState().name)
})
return () => {
// 取消订阅
unsubscribe()
}
}, [])
return (
<div>
<h2>{name}</h2>
</div>
)
}
export default PageD
dispatch
import React from "react"
import store from "../store/store"
const Button = () => {
return (
<>
<button
onClick={() => {
store.dispatch({type:"change-name"})
}}
>
change-name
</button>
<button
onClick={() => {
store.dispatch({type:"reset-name"})
}}
>
reset-name
</button>
</>
)
}
export default Button
dispatch-action
dispatch 只支持对象为参数,但是可以写一个函数返回对象,返回对象的函数可以定义一些逻辑,这个函数就是action
import React from "react"
import { changeName, resetName } from "../store/actionCreator/NameActionCrator"
import store from "../store/store"
const Button = () => {
return (
<>
<button
onClick={() => {
store.dispatch(changeName())
}}
>
change-name
</button>
<button
onClick={() => {
store.dispatch(resetName())
}}
>
reset-name
</button>
</>
)
}
export default Button
actionCreator
这样写的好处就是可以写一些逻辑。
function changeName() {
return { type: "change-name" }
}
function resetName() {
return { type: "reset-name" }
}
export { changeName, resetName }
二、多个reducer的使用
cityReducer
const state = {
city: "成都"
}
const cityReducer = (prevState = state, action) => {
const newState = { ...prevState }
switch (action.type) {
case "change-city":
newState.city = "北京"
return newState
case "reset-city":
newState.city = "成都"
return newState
default:
return prevState
}
}
export default cityReducer
nameReducer
const state = {
name: "zrs"
}
const nameReducer = (prevState = state, action) => {
const newState = { ...prevState }
switch (action.type) {
case "change-name":
newState.name = "名字已经被改变了"
return newState
case "reset-name":
newState.name = "zrs"
return newState
default:
return prevState
}
}
export default nameReducer
将多个reducer合并
使用 combineReducers 将多个reducer合并。
import {
legacy_createStore as createStore,
combineReducers
} from "redux"
import cityReducer from "./reducer/cityreducer"
import nameReducer from "./reducer/namereducer"
const rootReducer = combineReducers({
cityReducer,
nameReducer
})
const store = createStore(rootReducer)
export default store
订阅
订阅的时候需要添加对应reducer的名字
import React, { useState, useEffect } from "react"
import store from "../store/store"
const PageE = () => {
const [name, setname] = useState(store.getState().nameReducer.name)
useEffect(() => {
const unsubscribe = store.subscribe(() => {
setname(store.getState().nameReducer.name)
})
return () => {
unsubscribe()
}
}, [])
return <h2>{name}</h2>
}
export default PageE
三、在redux中使用异步-1
安装插件
npm install --save redux-thunk
配置 redux-thunk
import {
legacy_createStore as createStore,
combineReducers,
applyMiddleware
} from "redux"
import reduxThunk from "redux-thunk"
import cityReducer from "./reducer/cityreducer"
import nameReducer from "./reducer/namereducer"
import dataListReducer from "./reducer/dataListRdeducer"
const reducer = combineReducers({
cityReducer,
nameReducer,
dataListReducer
})
// 配置 redux-thunk
const store = createStore(reducer, applyMiddleware(reduxThunk))
export default store
在dispatch-action中使用异步
import axios from "axios"
function getList() {
// 因为有异步,所以这里需要返回一个函数
return (dispatch) => {
axios({
url: "https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=657515",
method: "get",
headers: {
"X-Client-Info":
'{"a":"3000","ch":"1002","v":"5.2.1","e":"16653811463674774018457601","bc":"110100"}',
"X-Host": "mall.film-ticket.cinema.list"
}
}).then((res) => {
console.log(res.data.data.cinemas)
dispatch({
type: "get-list",
payload: res.data.data.cinemas
})
})
}
}
export { getList }
使用含有异步dispatch-action
import React, { Component } from "react"
import { getList } from "../store/actionCreator/dataListActionCreator"
import store from "../store/store"
export default class PageB extends Component {
state = {
list: store.getState().dataListReducer.list
}
componentDidMount() {
if (store.getState().dataListReducer.list.length === 0) {
// 使用action获取数据
store.dispatch(getList())
} else {
console.log("使用缓存的数据")
}
this.unsubscribe = store.subscribe(() => {
this.setState({
list: store.getState().dataListReducer.list
})
})
}
componentWillUnmount() {
this.unsubscribe()
}
render() {
return (
<div>
{this.state.list.map((item) => {
return <div key={item.name}>{item.name}</div>
})}
</div>
)
}
}
四、在redux中使用异步-2
安装插件
npm install --save redux-promise
使用redux-promise的方式
import {
legacy_createStore as createStore,
combineReducers,
applyMiddleware
} from "redux"
import cityReducer from "./reducer/cityreducer"
import nameReducer from "./reducer/namereducer"
import dataListReducer from "./reducer/dataListRdeducer"
import reduxPromise from "redux-promise"
const reducer = combineReducers({
cityReducer,
nameReducer,
dataListReducer
})
// 配置 redux-promise
// applyMiddleware 里面可以配置很多中间件
const store = createStore(reducer, applyMiddleware(reduxPromise))
export default store
在dispatch-action中使用异步
import axios from "axios"
async function getList() {
let res = await axios({
url: "https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=657515",
method: "get",
headers: {
"X-Client-Info":
'{"a":"3000","ch":"1002","v":"5.2.1","e":"16653811463674774018457601","bc":"110100"}',
"X-Host": "mall.film-ticket.cinema.list"
}
})
return {
type: "get-list",
payload: res.data.data.cinemas
}
}
export { getList }
使用含有异步的dispatch-action
import React, { Component } from "react"
import { getList } from "../store/actionCreator/dataListActionCreator"
import store from "../store/store"
export default class PageB extends Component {
state = {
list: store.getState().dataListReducer.list
}
componentDidMount() {
if (store.getState().dataListReducer.list.length === 0) {
// 使用action获取数据
store.dispatch(getList())
} else {
console.log("使用缓存的数据")
}
this.unsubscribe = store.subscribe(() => {
this.setState({
list: store.getState().dataListReducer.list
})
})
}
componentWillUnmount() {
this.unsubscribe()
}
render() {
return (
<div>
{this.state.list.map((item) => {
return <div key={item.name}>{item.name}</div>
})}
</div>
)
}
}
五、redux-devtool
安装该开发工具之后,需要配置这个代码,才能在浏览器中看到具体的state。
import {
legacy_createStore as createStore,
combineReducers,
applyMiddleware,
compose
} from "redux"
// 以下代码的配置可以实现让 redux-devtool 获取应用中的状态
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const store = createStore(
reducer,
composeEnhancers(applyMiddleware(reduxPromise))
)
export default store
六、react-redux
这个工具库是来简化redux的操作的,因为使用redux的核心库会使得需要手动取消订阅或者手动订阅,但是这个库将redux中的状态加工为组件的props,就免去了手动订阅和手动取消订阅,因为react的state或者props发生改变,那么界面就会刷新。
安装
npm install --save react-redux
在根组件上配置
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App"
import { HashRouter as RouterSelf } from "react-router-dom"
import store from "./store/store"
import { Provider } from "react-redux"
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(
<RouterSelf>
<Provider store={store}>
<App />
</Provider>
</RouterSelf>
)
使用connect修改状态
import React, { Component } from "react"
import { getList } from "../store/actionCreator/dataListActionCreator"
import { connect } from "react-redux"
class PageB extends Component {
componentDidMount() {
if (this.props.list.length === 0) {
this.props.getList()
}
}
render() {
return (
<>
{this.props.list.map((item) => {
return <div key={item.name}>{item.name}</div>
})}
</>
)
}
}
const mapStateToProps = (state) => {
return {
list: state.dataListReducer.list
}
}
const mapDispatchToProps = {
getList
}
export default connect(mapStateToProps, mapDispatchToProps)(PageB)
connect()
该方法的作用就是:将state和dispatch混入到原组件的props里面。
函数接收两个参数:
第一个参数是一个函数,该函数有一个形参,就是所有的状态值,可以在这个函数中返回需要的状态即可。
第二个参数就是一个对象,对象里面可以书写对应的actionCreator。