繁体   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