使用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
相关产品推荐
相关产品推荐

