React useState点击行后状态渲染滞后问题求助
问题:受控输入组件渲染滞后,展示上一次数据
使用受控输入组件时,将API响应传递给子组件<AdminInvociceDetail>,点击数据行后,子组件总是渲染上一次的数值。
传递数据行ID的父组件代码:
<AdminInvociceDetail row={invoiceRowClicked} />
子组件完整代码:
import React, { useState, useEffect } from "react"; import { useFetchInvoiceQuery, useUpdateInvoiceMutation, } from "../../features/Invoices/InvoiceSlice"; import { useNavigate, Link } from "react-router-dom"; import "./Admin.css"; const AdminInvociceDetail = ({ row }) => { const { data } = useFetchInvoiceQuery(row); const [UpdateInvoice] = useUpdateInvoiceMutation(); //* state for the form const [Id, setId] = useState(""); const [billtoname, setBillToName] = useState(""); const [clientname, setClientName] = useState(""); const [offc, setOffc] = useState(""); const [matterNo, setMatterNo] = useState(""); useEffect(() => { setId(data?.ID); setBillToName(data?.BillToName); setOffc(data?.OFFC); setClientName(data?.ClientName); setMatterNo(data?.MatterNo); }, [row]); function ButtonLink({ to, children, className }) { return ( <Link to={to}> <button className={className}>{children}</button> </Link> ); } return ( <div> <div class="box"> <form class="ui form" onSubmit={handleSubmit}> <h4 class="ui dividing header labels">Invoice Detail:</h4> <div class="two fields"> <div class="field"> <label className="labels">Bill To Name</label> <input type="text" name="BillToName" placeholder="Bill To Name" required onChange={(e) => setBillToName(e.target.value)} value={billtoname || ""} /> </div> <div class="field"> <label className="labels">Client Location</label> <select class="ui fluid dropdown" required onChange={(e) => setClientName(e.target.value)} value={clientname || ""} > <option value="">Location</option> <option value="Becker - Tampa">Becker - Tampa</option> <option value="Becker - Orlando">Becker - Orlando</option> <option value="Becker - West Palm Beach"> Becker - West Palm Beach </option> <option value="Becker - Fort Myers">Becker - Fort Myers</option> <option value="Becker - Coral Gables"> Becker - Coral Gables </option> <option value="Becker - Fort Lauderdale"> Becker - Fort Lauderdale </option> <option value="Becker - Morristown">Becker - Morristown</option> <option value="Becker - Bradenton">Becker - Bradenton</option> <option value="Becker - Stuart">Becker - Stuart</option> <option value="Becker - Naples">Becker - Naples</option> <option value="Becker - Sarasota">Becker - Sarasota</option> <option value="Becker - Fort Walton Beach"> Becker - Fort Walton Beach </option> <option value="Becker - New York">Becker - New York</option> <option value="Becker - Mount Laurel"> Becker - Mount Laurel </option> <option value="Becker - Red Bank">Becker - Red Bank</option> <option value="Becker - Tallahassee"> Becker - Tallahassee </option> </select> </div> </div> <div class="two fields"> <div class="field"> <label className="labels">Office</label> <select class="ui fluid dropdown" required onChange={(e) => setOffc(e.target.value)} name="offc" value={offc || ""} > <option value="">Office</option> <option value="TAL">TAL</option> <option value="ORL">ORL</option> <option value="WPB">WPB</option> <option value="FTM">FTM</option> <option value="MIA">MIA</option> <option value="FTL">FTL</option> <option value="MOR">MOR</option> <option value="STR">STR</option> <option value="NAP">NAP</option> <option value="BDT">BDT</option> <option value="SAR">SAR</option> <option value="FTW">FTW</option> <option value="TAM">TAM</option> <option value="MTL">MTL</option> <option value="MOR">MOR</option> <option value="RB">RB</option> <option value="NY">NY</option> <option value="DC">DC</option> </select> </div> <div class="field"> <label className="labels">Matter No</label> <input type="text" name="MatterNo" placeholder="Matter No" onChange={(e) => setMatterNo(e.target.value)} value={matterNo || ""} /> </div> </div> <ButtonLink to="/" className="back-button"> Back to Invoice </ButtonLink> <button class="submit-button">Submit Invoice</button> <div class="fields"></div> </form> </div> </div> ); }
问题原因:
useEffect的依赖数组设置为[row],当row变化时触发执行,但此时useFetchInvoiceQuery(row)返回的data仍为上一次请求的缓存结果(新API请求尚未完成),导致用旧数据更新表单状态,出现滞后。- 新的API数据返回后,
useEffect未监听data变化,无法同步更新表单状态。
解决方案:
1. 修正useEffect依赖,监听data变化
将useEffect的依赖改为data,确保新API数据返回时立即同步表单状态:
useEffect(() => { if (data) { // 避免data为undefined时更新 setId(data.ID); setBillToName(data.BillToName); setOffc(data.OFFC); setClientName(data.ClientName); setMatterNo(data.MatterNo); } }, [data]);
2. (可选)直接使用API数据作为受控组件数据源
如果不需要保留用户编辑后的临时状态,可以跳过本地useState,直接用data作为输入框的value,减少同步问题:
<input type="text" name="BillToName" placeholder="Bill To Name" required onChange={(e) => setBillToName(e.target.value)} value={data?.BillToName || ""} />
注意:这种方式下,API数据更新会覆盖用户输入,适合仅展示或需要严格同步API数据的场景。
3. 确保RTK Query参数变化时重新请求
如果存在缓存导致的旧数据问题,调用useFetchInvoiceQuery时添加配置,强制参数变化时重新请求:
const { data } = useFetchInvoiceQuery(row, { refetchOnMountOrArgChange: true, });
内容的提问来源于stack exchange,提问作者cruz
相关产品推荐
相关产品推荐

