React useState 不渲染当前的 onClick

React useState not rendering the current onClick

提问人:cruz 提问时间:11/17/2023 最后编辑:Drew Reesecruz 更新时间:11/17/2023 访问量:51

问:

我对我尝试执行的代码感到困惑。我正在使用受控输入,并将响应从 API 传递到子组件,但它正在呈现最后一个值。

这是我的代码。

传递我当前尝试显示的数据行的 ID:

<AdminInvociceDetail row={invoiceRowClicked} />

接收 ID 的组件

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>
  );

当我单击行时,状态滞后。不知道我在这里错过了什么。

javascript reactjs react-hooks redux-toolkit rtk-query

评论


答:

1赞 Drew Reese 11/17/2023 #1

如果我理解正确,问题是本地状态没有正确更新以按值匹配查询的数据,那么问题似乎是更新本地状态的钩子具有不正确的依赖关系。rowuseEffect

与其使用它,不如使用 ,这样当查询的结果更新时,效果可以运行并更新本地状态。如果已经有缓存的查询数据,还可以将初始状态值直接传递给挂钩。rowdatadatauseState

例:

const AdminInvociceDetail = ({ row }) => {
  const { data } = useFetchInvoiceQuery(row);
  const [UpdateInvoice] = useUpdateInvoiceMutation();

  // state for the form
  const [Id, setId] = useState(data?.ID);
  const [billtoname, setBillToName] = useState(data?.BillToName);
  const [clientname, setClientName] = useState(data?.ClientName);
  const [offc, setOffc] = useState(data?.OFFC);
  const [matterNo, setMatterNo] = useState(data?.MatterNo);

  useEffect(() => {
    setId(data?.ID);
    setBillToName(data?.BillToName);
    setOffc(data?.OFFC);
    setClientName(data?.ClientName);
    setMatterNo(data?.MatterNo);
  }, [data]); // <-- data is external dependency, not row

  ...

使用 React 钩子时,强烈建议将 eslint-plugin-react-hooks 插件添加到您的 eslint 配置中,以便通过 IDE 轻松识别缺失和/或不正确的钩子依赖项。

评论

1赞 Ross Allen 11/17/2023
我还建议使用 ESLint 和 eslint-plugin-react-hooks,它们会显示依赖数组中缺少的错误。data
1赞 Drew Reese 11/17/2023
@RossAllen 精彩的补充,谢谢。
0赞 cruz 11/17/2023
哇。我想踢我自己。谢谢德鲁。这成功了
0赞 cruz 11/17/2023
并感谢您的推荐!!!