React 不渲染长字符串列表。

huangapple go评论72阅读模式
英文:

React not rendering long list of strings

问题

在React中,我有一个长数组,包含600多个字符串项。我有一个map函数,用于将这些字符串列在日志中。当我将空列表更新以添加所有字符串时,更新几乎是立即的,但HTML本身需要很长时间才能更新/根本不更新。只有当我更改代码并触发某种快速重新加载时,HTML才会更新,除此之外它没有响应。

我最初怀疑列表没有渲染是因为列表过长,但在尝试了一个只有2或3项的测试列表后,仍然不起作用。现在我认为这是因为我通过WebSocket获取列表中的项目。

我使用SWR来获取日志,而reducer hook只是一个更容易push的状态数组。SWR是NextJS(我的技术栈)推荐的获取数据的方式,但在大多数情况下,它只是一个普通的WebSocket。我像这样映射logs数组。

{logs.map((log, index) => {
  return (
    <span
      key={index}
    >
      {log}
    </span>
  );
})}

如何使用WebSocket来获取数组的即时更新?

英文:

I have a long array in React, over 600 items of strings. I have a map function that lists these strings in a log. When I update the empty list to add all the strings, the update is fairly immediate but the HTML itself takes forever to update/doesn't update at all. It's only when I change the code and trigger some sort of fast reload does the HTML update, other than that it's unresponsive.

My original suspicion was that the list wasn't rendering because the list was overly long, but after trying it with a test list of just 2 or 3 items, it still didn't work. Now I think it's due to the fact that I'm fetching the items in a list through a WebSocket.

  const [logs, pushLogs] = useReducer(
    (prev, next) =&gt; {
      prev.push(...next);

      return prev;
    },
    [&quot;Initializing...&quot;]
  );
  useSWRSubscription(
    `ws://${host}/api/users/logs?id=${props.id}`,
    (key, { next }) =&gt; {
      const socket = new WebSocket(key);
      socket.addEventListener(&quot;message&quot;, ({ data }) =&gt; {
        pushLogs(data.split(&quot;\n&quot;));

        if (data.includes(&quot;Finished&quot;)) {
          return () =&gt; socket.close();
        }

        return next(null, data);
      });
      socket.addEventListener(&quot;error&quot;, (event) =&gt; next(event.error));
      return () =&gt; socket.close();
    }
  );

I'm using SWR to fetch the logs and the reducer hook is just a state array that I can push to more easily. SWR is the NextJS (my stack) recommended way to fetch things but for the most part it's just an ordinary WebSocket. I map the logs array like this.

{logs.map((log, index) =&gt; {
  return (
    &lt;span
      key={index}
    &gt;
      {log}
    &lt;/span&gt;
  );
})}

How can I use the WebSocket to get immediate updates to my array?

答案1

得分: 1

你的问题在于你使用 push 方法对数组进行了修改。由于数组仍然是同一个对象,React 不知道它已经改变了。React 是通过引用而不是值进行比较的。

根据React文档,以下是一种React可以识别的向数组添加元素的方式:

> push() 方法会修改一个数组,这并不是你想要的…
>
> 相反,创建一个包含现有项目和新项目的新数组。有多种方法可以做到这一点,但最简单的方法是使用... 数组扩展语法。

英文:

Your problem is you're mutating the Array by using push. Since the Array is still the same object React doesn't know it has changed. React compares by reference and not by value.

From the React docs, here is how you add to an Array in a way that React can see:

> push() will mutate an array, which you don’t want...
>
> Instead, create a new array which contains the existing items and a
> new item at the end. There are multiple ways to do this, but the
> easiest one is to use the ... array spread syntax

huangapple
  • 本文由 发表于 2023年6月29日 03:28:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76576179.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定