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

使用React Redux Toolkit触发action后,Modal意外重新打开的问题

解决Next.js中Redux Toolkit dispatch触发模态框重新打开的问题

问题核心原因

模态框在dispatch后重新打开,通常是以下几个原因导致:

  • 表单提交未阻止默认行为,触发页面刷新
  • 模态框的显示状态依赖了Redux中被dispatch修改的字段,导致组件重渲染时模态框被重新触发
  • 组件未做渲染优化,dispatch后触发不必要的重渲染

针对性解决方案

1. 阻止表单默认提交行为

如果handleAddAddress是绑定在表单的onSubmit事件上,必须调用e.preventDefault()避免页面刷新——这是最常见的触发模态框重启的原因:

import { useDispatch } from 'react-redux';
import { saveAddress } from './address.slice';
import { useState, useCallback } from 'react';

const AddressForm = () => {
  const dispatch = useDispatch();
  const [modalVisible, setModalVisible] = useState(true); // 用本地state控制模态框显示

  // 用useCallback稳定函数引用,避免不必要重渲染
  const handleAddAddress = useCallback(async (e, data) => {
    e.preventDefault(); // 关键:阻止表单默认提交行为

    // 直接构造JS对象,无需手动JSON.stringify(axios会自动序列化)
    const addressForm = {
      userName: data.userName,
      userAddress: data.userAddress,
      userAddress2: "",
      userCity: data.userCity,
      userPincode: data.userPincode,
      userState: data.userState,
      userEmail: data.userEmail,
      userMobileNumber: data.userMobileNumber,
      isDefault: true,
    };

    try {
      await dispatch(saveAddress({ addressForm })).unwrap();
      setModalVisible(false); // 提交成功后手动关闭模态框
    } catch (err) {
      console.error('地址保存失败:', err);
      // 这里可以添加错误提示逻辑
    }
  }, [dispatch]);

  return (
    <Modal visible={modalVisible} onCancel={() => setModalVisible(false)}>
      <form onSubmit={(e) => handleAddAddress(e, formData)}>
        {/* 表单输入项 */}
        <button type="submit">保存地址</button>
      </form>
    </Modal>
  );
};

export default AddressForm;

2. 修正Redux异步请求逻辑

你的address.slice.js存在两个问题:一是手动传递JSON字符串导致后端解析异常,二是错误捕获时变量名写错,修正如下:

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

export const saveAddress = createAsyncThunk(
  "address/saveAddress",
  async ({ addressForm }, { getState, rejectWithValue }) => {
    const state = getState();
    try {
      const res = await axios({
        method: "post",
        url: `${process.env.API_BASE_URL}/api/v1/saveaddress`,
        data: addressForm, // 直接传JS对象,axios自动处理JSON序列化
        headers: {
          Authorization: `Bearer ${state.auth.userToken}`,
          // axios会自动添加Content-Type: application/json,无需手动声明
        },
      });
      return res.data;
    } catch (error) {
      if (!error.response) {
        throw error; // 修正变量名:err → error
      }
      return rejectWithValue(error.response.data);
    }
  }
);

const addressSlice = createSlice({
  name: "address",
  initialState: {
    addresses: [],
    pincodeState: {},
    httpErr: [],
    loading: false, // 补充初始loading状态
  },
  reducers: {},
  extraReducers: {
    [saveAddress.pending]: (state) => {
      state.loading = true;
      state.httpErr = []; // 清空之前的错误
    },
    [saveAddress.fulfilled]: (state, action) => {
      state.loading = false;
      state.addresses = action.payload.addresses;
      localStorage.setItem("addresses", JSON.stringify(state.addresses));
    },
    [saveAddress.rejected]: (state, action) => {
      state.loading = false;
      state.httpErr = action.payload || ['请求失败'];
    },
  },
});

export default addressSlice.reducer;

3. 优化组件渲染性能

用React.memo包裹模态框内的表单组件,避免因父组件重渲染导致的不必要更新:

import React from 'react';

const AddressForm = React.memo(({ onSubmit }) => {
  // 表单逻辑...
});

export default AddressForm;

内容的提问来源于stack exchange,提问作者Amit Kumar Das

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 14:40:48