Redux-thunk https://cnodejs.org/api/v1/topics
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 const reducer = ( state = { bannerList: [], proList: [] }, { type, payload } ) => { switch (type) { case 'CHANGE_BANNER_LIST': return { ...state, bannerList: payload } case 'CHANGE_PRO_LIST': return { ...state, proList: payload } default: return state } } export default reducer // actionCreator 本质是一个带有 dispatch 参数的函数 const action = { getBannerListAction (dispatch) { // 因为此接口不需要参数,所有拥有了默认参数 dispatch getBannerList().then(res => { dispatch({ type: 'CHANGE_BANNER_LIST', payload: res.data }) }) }, getProListAction (params) { // 组件调用需要传递参数 return (dispatch) => { getProList(params).then(res => { dispatch({ type: 'CHANGE_PRO_LIST', payload: res.data }) }) } } } export default action getBannerList () { dispatch(action.getBannerListAction) // 因为没有参数,所以不加() }, getProList () { dispatch(action.getProListAction({ count: 2, limitNum: 3 })) // 因为有参数,所以加() }
RTK:操作redux 的一个工具包
第一步: 需要下载安装
1 npm install @reduxjs/toolkit
第二步: 在src目录下新建 store目录, 在该目录下创建index.js 文件, 内容可以使用官网的示例代码:
redux官网地址: https://cn.redux.js.org/introduction/getting-started
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import { createSlice, configureStore } from '@reduxjs/toolkit' ;const counterSlice = createSlice ({ name : 'counter' , initialState : { count : 0 }, reducers : { addCount : (state ) => { state.count +=1 }, jianCount : (state,action ) => { state.count -= action.payload } } }) export const { addCount, jianCount } = counterSlice.actions ;const store = configureStore ({ reducer : counterSlice.reducer }) export default store
在项目入口文件中,引入 store, 并挂载到根组件
1 2 3 4 5 6 7 8 9 10 11 12 import store from './store' ;import { Provider } from 'react-redux' ;const root = ReactDOM .createRoot (document .getElementById ('root' ));root.render ( <Provider store ={store} > <Router > <App /> </Router > </Provider > );
在类组件页面中使用 store 仓库中的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import React , { Component } from 'react' ;import { connect } from 'react-redux' ;import { addCount, jianCount } from '../../store' ;class Myclass extends Component { render ( ) { console .log (this ); return ( <div > 类组件中使用 <p > <button onClick ={this.props.add} > 同步+1</button > count:{this.props.count} <button onClick ={this.props.jian} > 同步-1</button > </p > </div > ); } } function mapstatetoprops (state ) { return state } function mapdispatchtoprops (dispatch ) { return { add ( ) { dispatch (addCount (10 )) }, jian ( ) { dispatch (jianCount (5 )) }, } } export default connect (mapstatetoprops, mapdispatchtoprops)(Myclass );
在函数组件页面中使用store 仓库中的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import React from 'react' ;import { useSelector, useDispatch } from 'react-redux' ;import { addCount, jianCount } from '../../store/index' const Myfun = ( ) => { const { count } = useSelector ((state ) => state); const dispatch = useDispatch (); return ( <div > 函数组件中使用 <p > {/*调用addCount方法*/} <button onClick ={() => { dispatch(addCount(2)) }}>+2</button > count:{count} {/*调用jianCount方法*/} <button onClick ={() => { dispatch(jianCount(2)) }}>-2</button > </p > </div > ); } export default Myfun ;
以上是最简单的操作方式, 但是当操作异步方法时, 并需要将store仓库模块化
将如上仓库进行模块化, 不同的模块管理自己仓库的数据, 在store 目录下, 新建reducers, 在该目录中新建userReducer.js 和 goodsReducer.js
goodsReducer.js 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import axios from 'axios' ;import { createSlice } from '@reduxjs/toolkit' ;const goodsSlice = createSlice ({ name : 'goods' , initialState : { count : 0 , goodArr : [] }, reducers : { addCount : (state, action ) => { state.count += action.payload }, jianCount : (state, action ) => { state.count -= action.payload }, addgoods : (state, action ) => { state.goodArr = action.payload } } }) export const { addCount, jianCount, addgoods } = goodsSlice.actions ;export const asyncAddGoods = (payload ) => (dispatch ) => { axios.get ('http://kumanxuan1.f3322.net:8001/index/index' ).then (res => { console .log (11 , res); dispatch (addgoods (res.data .data .banner )) }) } export default goodsSlice
userReducer.js 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import { createSlice } from '@reduxjs/toolkit' ;const userSlice = createSlice ({ name : 'user' , initialState : { userinfo : { name : '张三' , age : 20 } }, reducers : { edituser : (state, action ) => { state.userinfo = action.payload }, addAge : (state, action ) => { state.userinfo .age += action.payload } } }) export const { edituser, addAge } = userSlice.actions ;export const asyncedituser = (payload ) => (dispatch ) => { setTimeout (() => { dispatch (edituser (payload)) }, 1000 ) } export default userSlice
store文件中的index.js 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import { configureStore } from '@reduxjs/toolkit' ;import goodsSlice from './reducers/goodsReducer' ;import userSlice from './reducers/userReducer' ;const store = configureStore ({ reducer : { goods : goodsSlice.reducer , user : userSlice.reducer } }) export default store
将如上的store 导入 项目的入口文件index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import store from './store' ;import { Provider } from 'react-redux' ;const root = ReactDOM .createRoot (document .getElementById ('root' ));root.render ( <Provider store ={store} > <Router > <App /> </Router > </Provider > );
在类组件的页面中使用store 仓库的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import React , { Component } from 'react' ;import { connect } from 'react-redux' ;import { addCount, jianCount, asyncAddGoods } from '../../store/reducers/goodsReducer' ;class Myclass extends Component { render ( ) { return ( <div > 类组件中使用 <div > <button onClick ={this.props.add} > 同步+10</button > count:{this.props.goods.count} <button onClick ={this.props.jian} > 同步-10</button > <button onClick ={this.props.addAsync} > 异步+100</button > <ul > {this.props.goods.goodArr.map((item) => { return <li key ={item.id} > <img src ={item.image_url} /> </li > })} </ul > </div > </div > ); } } function mapstatetoprops (state ) { return state } function mapdispatchtoprops (dispatch ) { return { add ( ) { dispatch (addCount (10 )) }, jian ( ) { dispatch (jianCount (10 )) }, addAsync ( ) { dispatch (asyncAddGoods ()) }, } } export default connect (mapstatetoprops, mapdispatchtoprops)(Myclass );
在函数组件中使用 store 仓库数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import React from 'react' ;import { useSelector, useDispatch } from 'react-redux' ;import { addAge, asyncedituser } from '../../store/reducers/userReducer' ;const Myfun = ( ) => { const { userinfo } = useSelector ((state ) => state.user ); const dispatch = useDispatch (); return ( <div > 函数组件中使用 <p > <button onClick ={() => { dispatch(addAge(1)) }}>用户年龄+1</button > <button onClick ={() => { dispatch(asyncedituser({ name: "测试", age: 30 })) }}>修改用户信息</button > userinfo:{userinfo.name} -- {userinfo.age} </p > </div > ); } export default Myfun ;
createSelector
1 2 3 4 5 6 import { createSelector } from '@reduxjs/toolkit'; //相当于vue里的computed let fn = createSelector(state=>state.list.list,(list)=>list.filter(item=>item.title.length<10)) let filterList= useSelector(fn); //过滤的标题长度小于10