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

React模态框表单提交后UI无法稳定更新的问题求助

问题分析与解决思路

核心问题

提交表单后UI更新不稳定,根源是createRequest是异步操作,当前代码中直接调用fetchData,可能在新数据还未写入数据库时就执行查询,导致读取的仍是旧数据。同时fetchData的异步逻辑处理不规范,也可能加剧时序问题。直接用setSearchedMain(prev => [...prev, newRequest])虽然更新稳定,但缺失数据库生成的自增ID,无法满足后续操作需求。

解决步骤

  • 等待创建请求完成后再刷新数据:将handleSave改为异步函数,确保createRequest执行完成(数据写入数据库)后,再调用fetchData拉取最新列表。
  • 规范异步逻辑处理:在fetchData中使用await处理Promise,替代嵌套的then,让代码逻辑更清晰,避免时序混乱。
  • 优化列表key值:后续拿到数据库返回的自增ID后,将列表项的key从index替换为ID,避免列表更新时的渲染异常。
  • 重置表单状态:提交成功后清空表单状态,避免下次打开模态框时残留旧输入内容。

修改后的完整代码

import { useEffect, useState } from 'react';
import { Button, FloatingLabel, Form, Modal } from 'react-bootstrap';

import getAllRequests from '../../services/getAllRequests';
import createRequest from '../../services/createRequest';

const Main = () => {
    const [searchedMain, setSearchedMain] = useState([]);
    const [loading, setLoading] = useState(true);
    const [show, setShow] = useState(false);
    const [newRequest, setNewRequest] = useState({
        name: '',
        requestType: '',
        description: '',
    });

    const handleChange = (e) => {
        const { name, value } = e.target;
        setNewRequest((prev) => ({...prev, [name]: value}));
    };

    async function fetchData() {
        try {
            const res = await getAllRequests();
            setSearchedMain(res.data);
            setLoading(false);
        } catch (err) {
            console.error('获取数据失败:', err);
            setLoading(false);
        }
    }

    useEffect(() => {
        fetchData();
    }, []);

    const handleOpen = () => setShow(true);
    const handleClose = () => setShow(false);
    
    // 异步处理创建请求,确保写入完成后刷新数据
    const handleSave = async () => {
        try {
            await createRequest(newRequest);
            // 重置表单
            setNewRequest({
                name: '',
                requestType: '',
                description: '',
            });
            handleClose();
            fetchData();
        } catch (err) {
            console.error('创建请求失败:', err);
            // 可在此处添加用户可见的错误提示,如弹窗/Toast
        }
    };

    return loading ?
        <h1>Loading</h1>
        :
        <>
            <h1>Welcome</h1>
            <Modal show={show} onHide={handleClose}>
                <Modal.Header closeButton>
                    <Modal.Title>Add Request</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    <Form>
                        <FloatingLabel label="Name" className="mb-3">
                            <Form.Control 
                                name="name" 
                                value={newRequest.name}
                                onChange={handleChange} 
                            />
                        </FloatingLabel>
                        <FloatingLabel label="Request Type" className="mb-3">
                            <Form.Control 
                                name="requestType" 
                                value={newRequest.requestType}
                                onChange={handleChange} 
                            />
                        </FloatingLabel>
                        <FloatingLabel label="Description" className="mb-3">
                            <Form.Control 
                                name="description" 
                                value={newRequest.description}
                                onChange={handleChange} 
                            />
                        </FloatingLabel>
                    </Form>  
                </Modal.Body>
                <Modal.Footer>
                    <Button variant="secondary" onClick={handleClose}>
                        Cancel
                    </Button>
                    <Button variant="primary" onClick={handleSave}>
                        Save Changes
                    </Button>
                </Modal.Footer>
            </Modal>
            <table>
                <thead>
                    <tr>
                        <th onClick={handleOpen}>Add Request</th>
                    </tr>
                </thead>
                <tbody>
                    {searchedMain.map((request) => {
                        // 后续拿到自增ID后替换为request.id
                        return (
                            <tr key={request.id || request.record} {...request}>
                                <td>{request.record}</td>
                                <td>{request.name}</td>
                                <td>{request.requestedBy}</td>
                                <td>{request.description}</td>
                            </tr>
                        )
                    })}
                </tbody>
            </table>
        </>
}

export default Main;

额外说明

  • 需确保createRequest函数在数据成功写入数据库后才resolve Promise,这样await才能正确等待操作完成。
  • 给Form.Control绑定value,让表单成为受控组件,避免状态不一致。
  • 错误处理部分可根据需求添加用户友好的提示,比如用Toast组件展示错误信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:00:07