Redux入门:美团购物车列表小案例

引言

📒📒📒欢迎来到小冷的代码学习世界
博主的微信公众号想全栈的小冷,分享一些技术上的文章,以及解决问题的经验
当前专栏react系列

Redux

完整代码案例仓库 :https://gitee.com/cold-abyss_admin/react-redux-meituan

Redux是 React 最常用的集中状态管理工具,类似与VUE的pinia(vuex) 可以独立于框架运行

image-20241211182447283

使用思路:

  1. 定义一个reducer函数 根据当前想要做的修改返回一个新的状态
  2. 使用createStore方法传入reducer函数 生成一个store实例对象
    1. subscribe方法 订阅数据的变化(数据一旦变化,可以得到通知)
    2. dispatch方法提交action对象 告诉reducer你想怎么改数据
    3. getstate方法 获取最新的状态数据更新到视图中

image-20241211185420416

配置Redux

在React中使用redux,官方要求安装俩个其他插件-和react-redux

官方推荐我们使用 RTK(ReduxToolkit) 这是一套工具集合 可以简化书写方式

  • 简化store配置
  • 内置immer可变式状态修改
  • 内置thunk更好的异步创建
调试工具安装

谷歌浏览器搜索 redux-devtool安装 工具

依赖安装

#redux工具包
npm i @reduxjs/toolkit react-redux
#调试工具包
npm install --save-dev redux-devtools-extension

image-20241213153131189

store目录机构设计
  • 通常集中状态管理的部分都会单独创建一个store目录
  • 应用通常会有多个子store模块,所以创建一个modules进行内部业务的区分
  • store中的入口文件index.js 的作用是组合所有modules的子模块 并且导出store

image-20241211190849933

快速上手

使用react+redux 开发一个计数器 熟悉一下技术

image-20241211190956868

  1. 使用 Reacttoolkit 创建 counterStore

    import {
         
         createSlice} from "@reduxjs/toolkit";
    
    const counterStore= createSlice({
         
         
        name: "counter",
        // 初始化 state
        initialState: {
         
         
            count: 0
        },
        // 修改状态的方法
        reducers:{
         
         
            increment(state){
         
         
                state.count++
            },
            decrement(state){
         
         
                state.count--
            }
        }
    })
    
    // 解构函数
    const {
         
         increment,decrement}= counterStore.actions
    // 获取reducer
    const reducer = counterStore.reducer;
    export {
         
         increment,decrement}
    export default reducer
    
  2. index.js集合counter

    import {
         
         configureStore} from "@reduxjs/toolkit";
    import counterStore from "./modules/counterStore";
    const store = configureStore({
         
         
        reducer:{
         
         
            couner: counterStore,
        }
    })
    
    export default store
    
  3. 为React 注入store, react-redux负责把Redux和React链接 起来,内置 Provider组件 通过 store 参数把创建好的store实例注入到应用中 找到项目中的index.js

    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
          <Provider store={store}>
              <App />
          </Provider>
      </React.StrictMode>
    );
    
    
  4. 使用useSelector 获取到数据

    import {useSelector} from "react-redux";
    
    function App() {
      const {count} = useSelector(state => state.counter);
      return (
        <div className="App">
          {count}
        </div>
      );
    }
    
  5. 使用 钩子函数 useDispatch

    import {
         
         useDispatch, useSelector} from "react-redux";
    import {
         
         inscrement,descrement} from "./store/modules/counterStore"
    function App() {
         
         
      const {
         
         count} = useSelector(state => state.counter);
     const dispatch = useDispatch()
      return (
        <div className="App">
            <button onClick={
         
         ()=>dispatch(inscrement())}>+</button>
            {
         
         count}
            <button onClick={
         
         ()=>dispatch(descrement())}>-</button>
        </div>
      );
    }
    
    export default App;
    
    
  6. 查看效果

    image-20241211194212353

提交acntion传参

reducers的同步修改方法中添加action对象参数,在调用actionCreater参数的时候传递参数,参数会被传递到action对象的payload属性上

我们继续的改造一下counterStore

action这个对象参数有个固定的属性叫payload用来接收传参

image-20241212183228071

然后 app.js 添加两个按钮 用来传递参数

image-20241212183251405

效果

image-20241212183353807

Reudx action异步操作

区分同步和异步action

image-20241212192017617

如果action的内容是 object对象那就是同步action,如果是函数 那就是异步action

为什么我们需要异步action操作来使用请求 ?

例子:

我们有两种方式可以实现 隔五分钟 上蛋炒饭

一种是客人自己思考五分钟

一种是客人点好 叫服务员五分钟之后上

这个服务员就是 redux 我们刚希望相关aciton的操作都在redux里完成这个时候同步action就不能满足我们的需求了 所以需要使用异步action

​ 异步操作的代码变化不大,我们创建store的写法保持不变 ,但是在函数中用异步操作的时候需要一个能异步执行函数return出一个新的函数而我们的异步操作卸载新的函数中.

异步action中一般都会调用一个同步action

案例: 从后端获取到列表展示到页面

新建一个文件叫做 ChannelStore.js 然后编写对应的创建代码

import {
   
   createSlice} from "@reduxjs/toolkit";
import axios from "axios";
const  channelStore = createSlice({
   
   
    name: "channel",
    initialState: {
   
   
        channelList:[]
    },
    reducers:{
   
   
        setChannel(state, action){
   
   
            state.channelList=action.payload
        }
    }
})
const {
   
   setChannel}= channelStore.actions
// 异步请求
const fetchChannelList = ()=>{
   
   
    return async (dispatch)=>{
   
   
        const  res = await  axios.get('http://geek.itheima.net/v1_0/channels')
        dispatch(setChannel(res.data.data.channels))
    }
}

const reducer = channelStore.reducer;
export {
   
   fetchChannelList}
export default reducer

然后去store入口加入channelStore

import {
   
   configureStore} from "@reduxjs/toolkit";
import counterStore from "./modules/counterStore";
import channelStore from "./modules/channelStore";
const store = configureStore({
   
   
    reducer:{
   
   
        counter: counterStore,
        channel: channelStore,
    }
})

export default store

之后就可以在app.js加入代码

import {useDispatch, useSelector} from "react-redux";
import {useEffect} from "react";
import {fetchChannelList} from "./store/modules/channelStore";
function App() {
  const {channelList} = useSelector(state => state.channel);
 const dispatch = useDispatch()
    useEffect(() => {
        dispatch(fetchChannelList())
    }, [dispatch]);
  return (
      <div className="App">
          <ul>
              {channelList.map(item =><li key={item.id}>{item.name}</li>)}
          </ul>
      </div>

  );
}

export default App;

代码效果

image-20241212191240289

redux hooks

useSelector

它的作用是吧store中的数据映射到组件中

 const {
   
   count} = useSelector(state => state.counter);

这里的count其实对应的就是

image-20241211192355704

useDispatch

它的作用是生成提交 action对象的dispatch函数

import {
   
   useDispatch, useSelector} from "react-redux";
import {
   
   inscrement,descrement} from "./store/modules/counterStore"
function App() {
   
   
  const {
   
   count} = useSelector(state => state.counter);
 const dispatch = useDispatch()
  return (
    <div className="App">
        <button onClick={
   
   ()=>dispatch(inscrement())}>+</button>
        {
   
   count}
        <button onClick={
   
   ()=>dispatch(descrement())}>-</button>
    </div>
  );
}

export default App;

美团点餐界面小案例

下载模板地址:

git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷环渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值