簡體   English   中英

將對象字符串化以用於 useState() Hook 以避免重新渲染是一種好習慣嗎

[英]Is it good Practice to Stringify Object for useState() Hook To Avoid Re-Rendering

根據這個那個問題, 擴展運算符似乎用於更新useState鈎子中管理的對象。

我創建了一個超級簡單的例子並發現,即使對象的內容沒有改變,也會觸發重新渲染(很明顯,因為對象改變了):

import React from "react";

function useFriendStatus() {
  const [person, setPersonProps] = React.useState({name:'Mark',age:23});

  React.useEffect(() => {
    console.log("rerender");
    const interval = setInterval(() => {
      setPersonProps({...person});   //simply set the object again -> no content changed
      console.log('update');
    }, 1000);
    return () => clearInterval(interval);
  }, [person]);


  return person;
}

export default function App() {
  const person = useFriendStatus();

  return <div className="App">Hello World: {"" + person.name}</div>;
}

在這里,您可以看到我的分析器的屏幕截圖,顯示似乎觸發了重新渲染(即使顯示的名稱沒有更改):

在此處輸入圖片說明

我想知道這是否是一個“好習慣”,因為一切似乎都被重新渲染了。 有時,您從 API 中獲取深度嵌套的對象並將它們分解為超級簡單的非對象userState掛鈎是不可能的。

將所有內容字符串化不是更好嗎?

import React from "react";


function useFriendStatus() {
  const [person, setPersonProps] = React.useState(JSON.stringify({name:'Mark',age:23}));

  React.useEffect(() => {
    console.log("rerender");
    const interval = setInterval(() => {
      const personCopy=JSON.parse(person);
      setPersonProps(JSON.stringify({...personCopy}));
      console.log('update');
    }, 1000);
    return () => clearInterval(interval);
  }, [person]);


  return person;
}

export default function App() {
  const person = JSON.parse(useFriendStatus());

  return <div className="App">Hello World: {"" + person.name}</div>;
}

你在實踐中如何處理?

我創建了一個超級簡單的例子並發現,即使對象的內容沒有改變,也會觸發重新渲染(這很清楚,因為對象改變了)

它與對象的“內容”無關,您的組件會重新渲染,因為您創建了對象的淺拷貝{...person} (更改其引用)。

在渲染階段,React 會與之前的狀態進行淺層比較,以確定是否會發生渲染,而在 javascript 中, {} === {}始終為 false。

擴展運算符似乎用於更新 useState 掛鈎中管理的對象。

由於狀態應該被視為不可變的,因此通常使用擴展運算符進行淺拷貝。

“如果對象的名稱屬性發生變化,它應該只重新渲染”

在調用setState之前添加一個條件是很常見的:

React.useEffect(() => {
  const newPerson = { ...person }; // fetch from some source
  // or check if person.name !== newPerson.name
  if (!isEqual(person, newPerson)) {
    setPerson(newPerson);
  }
}, [person]);

暫無
暫無

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

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