You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中结合数组使用Signals(@preact/signals-react)?

使用@preact/signals-react优化大数据对象的组件重渲染

我尝试用@preact/signals-react解决大数据对象引发的组件重渲染问题,场景为从网络请求获取会实时更新的对象。

直接属性的优化效果良好

对于对象的直接属性,Signals能有效减少重渲染次数:

export function Root(){
  const mySignal = useSignal({ sub: { val: 1 }, arr: [{id: 1, name: "bob"}] });

  return <div>
    <Counter signal={mySignal} /> 
    <Array signal={mySignal} /> 
  </div>
}

function Counter({ signal }) {
  const counter = useComputed(() => signal.value.counter);

  return (
    <div>
      <p>{counter}</p>
      <button
        onClick={() => {
          signal.value = { ...signal.value, counter: signal.value.counter + 1 };
        }}
      >
        Increment
      </button>
    </div>
  );
}

点击递增按钮时,仅Counter组件会重渲染,使用useSignals()装饰器时效果一致。

数组处理的性能痛点

但处理数组时情况完全不同:

function ArrayConsumer({ mySignal }: { mySignal: MySignal }) {
  const arr = useComputed(() => mySignal.value.someArr);

  return (
    <>
      {arr.value.map((item) => (
        // 渲染并编辑{item.name}
        <ArrayItem key={item.id} item={item} />
      ))}
    </>
  );
}

由于直接使用arr.value,数组每次变化时整个列表都会触发重渲染。我原本期望官方能提供signalMap()这类专门处理列表的方法,但文档里只提到直接使用signal.value。

我考虑过把单个列表项包装成Signal,但不确定这是不是合理的实践。我原本以为Signals能提供和Mobx类似的性能与开发体验,但缺乏原生的列表支持会大幅降低它的实用性。

理想的实现方案

我期望能有这样的实现:

function ArrayItem(item) {
  // 假设item本身是一个Signal
  const name = useComputed(() => item.value.name);
  return (
    <div
      contentEditable
      onChange={(e) => (item.value = { ...item.value, name: e.target.value })}
    >
      {name}
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Uri Kutner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 13:15:57