引言:
在学习redux的时候,边学边做的笔记,大家学习的时候可以做一个参考。
redux的基本用法
这个图还比较的重要,画的也比较形象
流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存失败,源站可能有防盗链机制,建议将图片保存下来直接上传下上传(i4XOJGP1HMjn-1685105782761)(img.png)(img.png)]
使用redux的时候首先引入redux库
yarn add redux
然后创建store文件用来管理reducers
import { createStore } from 'redux'
import countReducer from './count_reducer'
// 将countReducer交给store进行管理
const store = createStore(countReducer)
export default store
创建一个示列
/**
* @author topu
* @date 2023/5/25
* @Description 1,改文件用于创建一个为count组件服务的reducer,reducer的本质是一个函数
* 2,reducer函会对接到两个参数,分别是之前的状态(preState),动作对象(action)
* @return number
*/
// 初始值
const initState = 0
function countReducer (preState = initState, action) {
const { type, data } = action
console.log(data)
// eslint-disable-next-line default-case
switch (type) {
case 'increment':
return preState + data
case 'decrement':
return preState - data
default:
return preState
}
}
export default countReducer
其中reducer的本质是一个函数
有两个参数,第一个一般用于充当返回值,第二个参数用于进行判断
当我们需要对reducer进行调用的时候,使用dispatch进行通信,一般会传入状态,数据
在reducer中一般对dispatch传入的数据进行判断,传入的数据存在action参数中
当数据改变的时候,我们要进行监听,要让页面调用render函数进行重新渲染,
在index中进行编写,可以直接监听全部的组件中store的改变
/**
* @author topu
* @date 2023/5/25
* @Description 全局监听store的改变,就不用到每个组件中进行监听
* @param {type} [param] 参数说明
* @return 返回值
*/
store.subscribe(() => {
root.render(<App/>)
})
dispatch是用来更改store的action的状态的,dispatch一般会上传一个对象,一般包括{type:’
@@@‘,data:’###'}
为了方便一般我们会将关系状态的单词用变量封装放到一个文件
/**
* 该模块用于定义action对象中type类型的常量值
*/
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
但是总是使用store.dispatch会有些不方便
我们将store.dispatch一般要传入的信息用函数封装,然后写到一个文件夹
/**
*这个文件专门为Count组件生成action对象
*/
import { DECREMENT, INCREMENT } from './constant'
export const createIncrementAction = data => ({ type: INCREMENT, data })
export const createDecrementAction = data => ({ type: DECREMENT, data })
// 用此进行封装
store.dispatch(createIncrementAction(value))
以上就是redux的基本用法,但是还有些高级用法还没有实现
redux的高级用法
异步action
要想实现异步,首先需要安装中间件,让store.dispatch能接受函数返回值,而不是仅仅是对象
yarn add redux-thunk
然后在store文件中进行配置
import { applyMiddleware, createStore } from 'redux'
import countReducer from './count_reducer'
// 引入中间件thunk
import thunk from 'redux-thunk'
// 将countReducer交给store进行管理
// 配置中间件thunk
const store = createStore(countReducer, applyMiddleware(thunk))
export default store
在这里我想让creatIncrementAction实现异步增加
这就需要插件react-thunk
redux-thunk可以让dispatch(action函数),action可以是一个函数
这里不是函数实现了异步操作,返回函数的作用是为了支持处理异步操作,利用Redux中间件来延迟执行Action,并在合适的时机派发相应的同步Action来更新状态。这种方式使得Redux能够更好地处理复杂的异步流程,并保持状态管理的一致性和可预测性。
因为返回函数我们可以通过中间件(thunk)来让store.dispatch()识别和处理
/**
*这个文件专门为Count组件生成action对象
*/
import { DECREMENT, INCREMENT } from './constant'
import store from './store'
export const createIncrementAction = data => ({ type: INCREMENT, data })
export const createDecrementAction = data => ({ type: DECREMENT, data })
// 实现createIncrementAction异步调用
export const createIncrementAsyncAction = (data, time) => {
return () => {
setTimeout(() => {
store.dispatch(createIncrementAction(data))
}, time)
}
}
// 进行调用
store.dispatch(createIncrementAsyncAction(value, 1000))
如何更加方便的使用redux
使用插件react-redux
模式图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-746sLL48-1685105782762)(img_1.png)]
react-redux简单的使用
先下载react-redux的库
npm install react-redux
然后将在文件中引入
import { connect } from 'react-redux'
import { Provider } from 'react-redux'
在App组件中进行绑定,这样相当于就可以绑定所有组件
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(
<Provider store={store}>
<App/>
</Provider>
)
这是About组件的代码
import React, { PureComponent } from 'react';
import { connect } from 'react-redux'
class About extends PureComponent {
constructor (props) {
super(props);
this.state = {};
}
render () {
// 拿到counter的数据
const { counter } = this.props
return (
<div>{counter}</div>
)
}
}
/**
* 这里是一个映射,将store中的counter数据和About组件连接起来
* 当counter的数据发生改变的时候就可以实时监听
* 那么如何在About组件中拿出counter的数据呢
* 数据存储在props中
*/
function mapStateToProps (state) {
return {
counter: state.counter
}
}
// connect他的返回值是一个高阶组件,他会接收两个函数,第一个函数是用来映射store的数据的,第二个是用来映射store的函数的
export default connect(mapStateToProps)(About)
**对其传入两个参数后执行connect函数(
这里的connect是一个高阶函数,第一个括号调用connect函数,然后返回一个高阶组件,在执行一次对高阶组件进行操作)
**
import React, { PureComponent } from 'react';
import { connect } from 'react-redux'
import {
createDecrementAction,
createIncrementAction
} from '../redux/contant_action'
class About extends PureComponent {
constructor (props) {
super(props);
this.state = {};
}
render () {
// 拿到counter的数据
const { counter } = this.props
return (
<h1>
<div>{counter}</div>
</h1>
)
}
}
/**
* 这里是一个映射,将store中的counter数据和About组件连接起来
* 当counter的数据发生改变的时候就可以实时监听
* 那么如何在About组件中拿出counter的数据呢
* 这里的函数,数据都存储在props中
* 这里的state就是获取store的状态值,这里就相当于reducer中每一项return的值
*/
function mapStateToProps (state) {
return {
counter: state
}
}
function mapDispatch (dispatch) {
return {
addNumber () {
dispatch(createIncrementAction())
},
subNumber () {
dispatch(createDecrementAction())
}
}
}
// connect他的返回值是一个高阶组件,他会接收两个函数,第一个函数是用来映射store的数据的,第二个是用来映射store的函数的
export default connect(mapStateToProps, mapDispatch)(About)
现在我们做一个演示
在constant.js文件中创建banners变量
export const CHANGE_BANNERS = 'change_banners'
在constant_action.js中封装返回状态的函数
export const CHANGE_BANNERS = 'change_banners'
在Category.jsx文件中实现
import React, { PureComponent } from 'react';
import axios from 'axios'
import { connect } from 'react-redux'
import { changeBannersActions } from '../redux/contant_action'
class Category extends PureComponent {
// 模拟请求数据
componentDidMount () {
axios({
method: 'GET',
url: 'http://topu.com',
}).then(res => {
const banners = res.data.data.banners
const { changeBanners } = this.props
changeBanners(banners)
}).catch(err => {
console.log(err)
})
}
render () {
return (
<button>change</button>
)
}
}
function mapSateToProps (state) {
return {
banners: state.banners
}
}
// function mapDispatchToProps (dispatch) {
// return {
// changeBanners (banners) {
// dispatch(changeBannersActions(banners))
// }
// }
// }
const mapDispatchToProps = (dispatch) => {
return {
changeBanners: (banners) => {
dispatch(changeBannersActions(banners))
}
}
}
export default connect(mapSateToProps, mapDispatchToProps)(Category)
工具
React Development Tools
Redux DevTools 但是生产环境要关闭这个工具 github有具体的代码