React-redux ReduxToolkit 的使用和封装 同步和异步修改initialState内的数据 详细说明
目录
reducers 官方推荐同步修改 initialState 方法
使用 connect 函数将 store 内的数据映射到组件 props内
认识Redux Toolkit
Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法。
redux的编写逻辑过于的繁琐和麻烦。
并且代码通常分拆在多个文件中(虽然也可以放到一个文件管理,但是代码量过多,不利于管理);
Redux Toolkit包旨在成为编写Redux逻辑的标准方式,从而解决上面提到的问题;
在很多地方为了称呼方便,也将之称为“RTK”;
安装Redux Toolkit:
npm install @reduxjs/toolkit react-redux
yarn add @reduxjs/toolkit react-redux
pnpm install @reduxjs/toolkit react-redux
Redux Toolkit的核心API主要是如下几个:
configureStore:
包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。
createSlice:
接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions。
createAsyncThunk:
接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分派动作类型的 thunk。
store的创建
configureStore用于创建store对象,常见参数如下:
reducer,将slice中的reducer可以组成一个对象传入此处;
middleware:可以使用参数,传入其他的中间件;
devTools:是否配置devTools工具,默认为true;
在 src 目录下创建一个store 文件夹 文件夹内创建 index.js 文件
-
// npm install @reduxjs/toolkit react-redux -S
-
import { configureStore } from '@reduxjs/toolkit'
-
// 导入 namesReducer 进行使用
-
import namesReducer from './features/names'
-
import asyncListReducer from './features/asyncList'
-
-
const store = configureStore({
-
reducer: {
-
names: namesReducer,
-
asyncList: asyncListReducer
-
},
-
// reduxjs/toolkit 默认是已经集成了 redux-thunk 和 redux-devtool 如果需要添加其他中间件可以使用middleware参数,传入其他的中间件
-
// middleware: [thunk, logger],
-
-
// 是否配置 devTool 工具,默认为 true 开发环境建议 true 生产环境建议 false
-
devTools: true
-
})
-
-
export default store
将 store 内的数据 在app组件内共享
使用 react-redux 给我们提供的 Provider 包裹 App 组件 传入store 进行数据共享
-
import { Provider } from 'react-redux'
-
import store from './Redux-Toolkit的使用/store'
-
import App from './Redux-Toolkit的使用/App'
-
-
// 编写 react 代码,并且通过 React 渲染出来对应的内容
-
const root = ReactDOM.createRoot(document.querySelector('#root'))
-
root.render(
-
<Provider store={store}>
-
<App name={'HachimanC'} />
-
</Provider>
-
)
重构代码 – 创建counter的reducer
创建 name.js 文件
我们先对names的reducer进行重构: 通过createSlice创建一个slice。
createSlice主要包含如下几个参数:
name:用户标记slice的名词
在之后的redux-devtool中会显示对应的名词;
initialState:初始化值
第一次初始化时的值;
reducers:相当于之前的reducer函数
对象类型,并且可以添加很多的函数;
函数类似于redux原来reducer中的一个case语句;
函数的参数:
✓ 参数一:state
✓ 参数二:调用这个action时,传递的action参数;
createSlice返回值是一个对象,包含所有的actions;
reducers 官方推荐同步修改 initialState 方法
这里的 reducers 是react官方推荐的同步修改的方法
-
import { createSlice } from '@reduxjs/toolkit'
-
const nameSlice = createSlice({
-
// 当前store的唯一id
-
name: 'names',
-
// 默认值
-
initialState: {
-
names: 'HachimanC'
-
},
-
/*
-
reducer(state = initState, action){
-
case 语句1:
-
获取 action 根据 action 修改 state
-
case 语句2:
-
获取 action 根据 action 修改 state
-
}
-
*/
-
// 这里的 reducers 是react官方推荐的同步修改的方法
-
reducers: {
-
addNamesAction(state, action) {
-
// action.payload 是传来的参数
-
console.log('addNamesAction', action)
-
state.names = state.names action.payload
-
},
-
subNamesAction(state, action) {}
-
}
-
})
-
export const { addNamesAction, subNamesAction } = nameSlice.actions
-
// 导出 nameSlice 内的 reducers
-
export default nameSlice.reducer
使用 connect 函数将 store 内的数据映射到组件 props内
-
import React, { PureComponent } from 'react'
-
import { connect } from 'react-redux'
-
import { addNamesAction } from './store/features/names'
-
export class Profile extends PureComponent {
-
addNames(nameValue) {
-
// console.log(nameValue)
-
this.props.addNamesHandler(nameValue)
-
}
-
render() {
-
const { names } = this.props
-
return (
-
<div>
-
<h2>Profile names: {names}</h2>
-
<button onClick={e => this.addNames(', lzumiShinichi')}>addNames</button>
-
<button onClick={e => this.addNames(', 大吉')}>addNames</button>
-
<button onClick={e => this.addNames(', OkabeRintaro')}>addNames</button>
-
</div>
-
)
-
}
-
}
-
const mapStateToProps = state => {
-
return {
-
names: state.names.names
-
}
-
}
-
const mapDispatchToProps = dispatch => ({
-
addNamesHandler(namesValue) {
-
dispatch(addNamesAction(namesValue))
-
}
-
})
-
export default connect(mapStateToProps, mapDispatchToProps)(Profile)
Redux Toolkit的异步操作
在之前的开发中,通过redux-thunk中间件让dispatch中可以进行异步操作。
◼ Redux Toolkit默认已经给我们继承了Thunk相关的功能:createAsyncThunk
◼ 当createAsyncThunk创建出来的action被dispatch时,会存在三种状态:
pending:action被发出,但是还没有最终的结果;
fulfilled:获取到最终的结果(有返回值的结果);
rejected:执行过程中有错误或者抛出了异常;
◼ 我们可以在createSlice的entraReducer中监听这些结果:
见下图
最后附上异步请求全部操作代码
-
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
-
import axios from 'axios'
-
-
// 导出
-
export const fetchAsyceList = createAsyncThunk('fetch/async', async () => {
-
const { data } = await axios.get('http://123.207.32.32:8000/home/multidata')
-
// const banners = data.data.banner.list
-
// const recommend = data.data.recommend.list
-
return data.data
-
})
-
-
const asyncListSlice = createSlice({
-
name: 'asyncListSlice',
-
initialState: {
-
banners: [],
-
recommend: []
-
},
-
reducers: {
-
changeBannerAction(state, { payload }) {},
-
changeRecommendAction(state, { payload }) {}
-
},
-
// 额外的 reducer 执行异步操作
-
extraReducers: {
-
// 计算属性名 [computedNames]
-
[fetchAsyceList.pending](state, action) {
-
console.log('fetchAsyncList 执行中还未有结果')
-
},
-
[fetchAsyceList.fulfilled](state, { payload }) {
-
console.log('fetchAsyncList 拿到结果了', payload)
-
state.banners = payload.banner.list
-
state.recommend = payload.recommend.list
-
},
-
[fetchAsyceList.rejected](state, action) {
-
console.log('fetchAsyncList 错误了')
-
}
-
}
-
})
-
-
export const { changeBannerAction, changeRecommendAction } = asyncListSlice.actions
-
-
export default asyncListSlice.reducer
-
import React, { PureComponent } from 'react'
-
import { connect } from 'react-redux'
-
import { fetchAsyceList } from './store/features/asyncList'
-
import { addNamesAction } from './store/features/names'
-
-
export class Home extends PureComponent {
-
componentDidMount() {
-
this.props.fetchAsyncList()
-
}
-
addNames(nameValue) {
-
// console.log(nameValue)
-
this.props.addNamesHandler(nameValue)
-
}
-
render() {
-
const { names, banners, recommend } = this.props
-
return (
-
<div>
-
<h2>Home names: {names}</h2>
-
<button onClick={e => this.addNames(', ErenYeager')}>addNames</button>
-
<button onClick={e => this.addNames(', Ayanokoji')}>addNames</button>
-
-
<div className="banners">
-
<h2>异步请求轮播图数据:</h2>
-
<ul>
-
{banners.map((item, index) => (
-
<li key={index}>{item.title}</li>
-
))}
-
</ul>
-
</div>
-
-
<div className="recommend">
-
<h2>异步请求推荐列表数据:</h2>
-
<ul>
-
{recommend.map((item, index) => (
-
<li key={index}>{item.title}</li>
-
))}
-
</ul>
-
</div>
-
</div>
-
)
-
}
-
}
-
-
const mapStateToProps = state => ({
-
names: state.names.names,
-
banners: state.asyncList.banners,
-
recommend: state.asyncList.recommend
-
})
-
-
const mapDispatchToProps = dispatch => ({
-
addNamesHandler(nameValue) {
-
dispatch(addNamesAction(nameValue))
-
},
-
subNames() {},
-
fetchAsyncList() {
-
dispatch(fetchAsyceList())
-
}
-
})
-
-
export default connect(mapStateToProps, mapDispatchToProps)(Home)
extraReducer的另外一种写法
extraReducer还可以传入一个函数,函数接受一个builder参数。
我们可以向builder中添加case来监听异步操作的结果:
使用 hooks 操作redux-toolkit
-
import React, { memo } from 'react'
-
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
-
// import { connect } from 'react-redux'
-
import { addNumberAction, subNumberAction } from './store/modules/counter'
-
-
const NamesCom = memo(() => {
-
console.log('names组件执行了一遍')
-
const { names } = useSelector(
-
state => ({
-
names: state.counter.names
-
}),
-
shallowEqual
-
)
-
return <h2>{names}</h2>
-
})
-
-
const ReduxHooks = memo(props => {
-
// const { count, addNumberHandler, subNumberHandler } = props
-
-
// 使用 useSelector 将 redux 中 store 的数据映射到组件内
-
const { count } = useSelector(
-
state => ({
-
count: state.counter.count
-
}),
-
// shallowEqual 可以对state.counter 内的 变量进行浅层比较 组件更新数据不会影响其他组件的渲染(性能优化)
-
shallowEqual
-
)
-
// 使用 useDispatch 派发 action 到 reducers 内
-
const dispatch = useDispatch()
-
const addNumberHandler = (num, isAdd) => {
-
if (isAdd) {
-
dispatch(addNumberAction(num))
-
return
-
}
-
dispatch(subNumberAction(num))
-
}
-
return (
-
<div>
-
<h2>ReduxHooks 使用</h2>
-
<h3>redux 里的count:{count}</h3>
-
<button onClick={e => addNumberHandler(5, true)}> 5</button>
-
<button onClick={e => addNumberHandler(5, false)}>-5</button>
-
<NamesCom />
-
<hr />
-
</div>
-
)
-
})
-
-
// 不使用 hooks
-
// const mapStateToProps = state => ({
-
// count: state.counter.count
-
// })
-
// const mapDispatchToProps = dispatch => ({
-
// addNumberHandler(num) {
-
// dispatch(addNumber(num))
-
// },
-
// subNumberHandler(num) {
-
// dispatch(subNumber(num))
-
// }
-
// })
-
// export default connect(mapStateToProps, mapDispatchToProps)(ReduxHooks)
-
-
export default ReduxHooks
Redux官方图
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgagjhc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24