You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Redux Toolkit中于Reducer更新后发送POST/PUT请求?

解决方案

Redux reducer必须是纯函数,绝对不能在里面发起异步请求(比如fetch/PUT),你有两种常用的合理方案来实现“更新本地状态后同步到数据库”的需求:

方案一:使用Redux Toolkit的createAsyncThunk(推荐)

将添加日志+同步数据库的逻辑封装在异步thunk中,既保证流程一致性,也便于处理请求的成功/失败状态。

步骤1:修改logSlice,添加异步thunk

import { createSlice, configureStore, createAsyncThunk } from '@reduxjs/toolkit';

// 定义异步thunk:先更新本地状态,再同步到数据库
export const addLogAndSync = createAsyncThunk(
  'log/addLogAndSync',
  async (logData, { dispatch }) => {
    // 1. 先更新本地Redux状态
    dispatch(logActions.addLog(logData));
    
    // 2. 发送PUT请求到数据库(替换为你的实际API地址)
    try {
      const response = await fetch('/api/logs', {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(logData),
      });
      
      if (!response.ok) throw new Error('日志同步失败');
      return await response.json();
    } catch (error) {
      console.error('同步错误:', error);
      // 可选:如果同步失败,回滚本地添加的日志(需要logData有唯一id)
      // dispatch(logActions.removeLog(logData.id));
      throw error;
    }
  }
);

const initialLogState = { logs: [] };

const logSlice = createSlice({
  name: 'log',
  initialState: initialLogState,
  reducers: {
    addLog(state, action) {
      state.logs.push(action.payload);
    },
    removeLog(state, action) {
      state.logs = state.logs.filter(log => log.id !== action.payload);
    },
    replaceLogs(state, action) {
      state.logs = action.payload;
    },
  },
  // 可选:处理请求的加载/完成/失败状态,比如添加加载提示
  extraReducers: (builder) => {
    builder
      .addCase(addLogAndSync.pending, (state) => {
        // state.isLoading = true; 可添加加载状态字段
      })
      .addCase(addLogAndSync.fulfilled, (state) => {
        // state.isLoading = false;
      })
      .addCase(addLogAndSync.rejected, (state) => {
        // state.isLoading = false;
      });
  }
});

// 其余store代码不变...

步骤2:修改组件的提交逻辑

不再直接dispatchaddLog,而是dispatch新的异步thunk:

const submitHandler = () => {
  let data = {
    message: message,
    attention: attention, 
    tech: tech,
    date: date,
    id: Date.now().toString() // 给日志添加唯一ID,方便后续处理
  }

  dispatch(addLogAndSync(data));
  setMessage('');
  setAttention(false); // 修正原代码的错误:布尔值状态要设为false而非空字符串
  setTech('');
}

方案二:在组件中用useEffect监听Redux状态变化

如果不想改动Redux层逻辑,可以在组件中监听logs状态的变化,每次有新日志添加时触发同步请求。

修改组件代码

import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { logActions } from '../../store';
import classes from './AddLogModal.module.css';

const AddLogModal = () => {
  const [message, setMessage] = useState('');
  const [attention, setAttention] = useState(false);
  const [tech, setTech] = useState('');
  const techs = useSelector(state => state.tech.techs);
  const logs = useSelector(state => state.log.logs); // 获取当前日志列表
  const date = new Date().toISOString().split('T')[0];
  const dispatch = useDispatch();

  // 监听日志列表变化,同步最新日志到数据库
  useEffect(() => {
    if (logs.length === 0) return;
    
    const latestLog = logs[logs.length - 1]; // 获取刚添加的日志
    const syncLog = async () => {
      try {
        const response = await fetch('/api/logs', {
          method: 'PUT',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(latestLog),
        });
        
        if (!response.ok) throw new Error('日志同步失败');
        console.log('日志同步成功');
      } catch (error) {
        console.error('同步错误:', error);
        // 可选:同步失败时删除本地日志
        // dispatch(logActions.removeLog(latestLog.id));
      }
    };
    
    syncLog();
  }, [logs, dispatch]); // 依赖日志列表和dispatch

  const submitHandler = () => {
    let data = {
      message: message,
      attention: attention, 
      tech: tech,
      date: date,
      id: Date.now().toString() // 添加唯一ID
    }

    dispatch(logActions.addLog(data));
    setMessage('');
    setAttention(false);
    setTech('');
  }

  // 组件return部分保持不变...
}

export default AddLogModal;

关键注意事项

  • 必须给每条日志添加唯一id,不管是前端临时生成还是后端返回,方便后续处理失败回滚、日志删除等操作。
  • 优先选择方案一:异步thunk将业务逻辑集中在Redux层,组件只负责触发action,代码更易维护、复用和测试。

内容的提问来源于stack exchange,提问作者09eric09

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 01:50:24