簡體   English   中英

React:從受控子輸入字段更新大型父記錄時如何保持性能?

[英]React: how to maintain performance when updating a large parent record from a controlled child input field?

想象一個允許用戶編輯賬單(發票)的 React 頁面。 賬單有相當多的可編輯字段,比如 100 個。此外,賬單可以有任意數量的行項目。 讓我們想象一下其中的 100 個,每個都有,比如說,20 個字段。

如果賬單是“父”,並且由 React 組件呈現,則行項目是“子”,每個都由“子”組件呈現。

我在父組件中維護帳單(及其行項目)的狀態,感覺不錯。

我想在子(行項目)組件中使用受控輸入字段。 然而,這意味着,至少天真地,即使我明智地使用 React.memo,每次按鍵都會導致父(賬單)組件中的狀態更新,以及一些重新渲染。

性能很快變得令人無法接受,即使只有 10 個訂單項,例如每次按鍵延遲 500-800 毫秒。 我已經做了一些性能調查,並且有幾個可能的答案,但我不會在這里報告它們,以免阻礙任何通往最佳答案的途徑。

必須有一個通用的解決方案,不是嗎? 我想在沒有表單庫的情況下這樣做,盡管我並不完全反對。

下面的精簡示例,只是為了演示基本架構。 該示例沒有性能問題。 :-)

幫助! 我缺少保持這種性能的魔力是什么?


const INITIAL_STATE = {
  invoiceNumber: "ABC123",
  customer: "Phil's Dills",
  lineItems: [
    { index: 0, item: "Pickles", quantity: 2 },
    { index: 1, item: "Pickle Juice", quantity: 5 },
  ]
}

export function Bill() {
  const [ bill, setBill ] = useState(INITIAL_STATE);

  function updateBill(updatedLineItem) {
    const newLineItems = [...bill.lineItems];
    newLineItems[updatedLineItem.index] = updatedLineItem;
    setBill({
      ...bill,
      lineItems: newLineItems
    })
  }

  return(
    <div id="parent">
    <h1>Bill {bill.invoiceNumber} for {bill.customer}</h1>
    {bill.lineItems.map((lineItem) => (
      <LineItem key={lineItem.index} line={lineItem} updateBill={updateBill} />
    ))}
    </div>
    );
}

function LineItem({ line, updateBill }) {
  function updateField(e) {
    updateBill({
      ...line,
      [e.target.id]: e.target.value
    }); 
  }

  return(
    <div id="child">
      <input id="quantity" value={line.quantity} onChange={updateField} />
      <input id="item" value={line.item} onChange={updateField} />
    </div>
    );
}```

我認為您的問題實際上是每次此組件重新渲染時都在重新創建updateBill ,這意味着每個子組件也將重新渲染,因為它們都將updateBill作為道具接收。 考慮使用useCallbackuseCallback updateBill函數:

const updateBill = useCallback(updatedLineItem => {
  setBill(bill => {
    const newLineItems = [...bill.lineItems];
    newLineItems[updatedLineItem.index] = updatedLineItem;
    return {
      ...bill,
      lineItems: newLineItems
    }
  })
}, []);

感謝大家的想法和建議。 你幫我理清了思路,我找到了問題所在。 bill會在每次按鍵時更新,它依賴於useEffect鈎子,事實證明,它非常昂貴並導致大量重新渲染。 我重構了useEffect並且我的按鍵性能現在非常可接受,即使在開發模式下也是如此。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM