为什么在React组件中使用此闭包时不起作用?

时间:2019-08-23 16:22:42

标签: javascript reactjs typescript

我试图了解为什么在从React组件中使用此闭包时无法按预期工作。

// state.ts
const state = { things: [] };

export function setThings(newThings: number[]) {
  state.things = newThings;
}
// App.tsx
import { setThings } from "./state";

function App() {
  const setThingsToArray = () => setThings([0, 1, 2]);
  return (
    <div>
      <button onClick={setThingsToArray}>Set things</button>
    </div>
  );
}

从非反应代码中调用setThings时,它可以正常工作。它将更改things的{​​{1}}属性。

但是,当我尝试从React组件(如App.tsx)中调用它时,它根本不起作用。调试显示,从state内部调用setThings时,它认为App是一个空数组state.things,即使{{1} }已经包含很多项目。

这似乎暗示React在某种程度上使用了[]的复制版本和state.things的复制版本。这怎么可能?它不应该作为简单的闭包并引用实际的setThings吗?


我不想使用像Hooks或Redux这样的React状态管理,因为我希望对数组中的更改具有高性能,因为这为具有大量粒子和每秒重绘的画布应用程序提供了动力。因此,如果我不需要React组件来显示数据,我就不必经历整个React生命周期。

编辑:为这个问题?‍♂️编写组件代码时,我犯了一个错误。我现在修复了。我的问题仍然存在。

编辑2:

因为@KevinB要求提供证据证明在其他地方调用state可以正确更新我的数组:https://youtu.be/Gp77NtqNQzo

画布中的每个“行星”都由数组中的一项表示。每个行星的坐标和加速度在每个帧上都会改变。当行星发生碰撞时,state被更改的行星阵列调用。之所以需要这样做,是因为多个行星可以彼此“碰撞”并合并为一个,从而形成setThings数组,其中删除了2个项,并添加了1个新项。

单击按钮将调用setThings,该数组仅包含一个行星对象。但正如您所见,它什么也没做。

2 个答案:

答案 0 :(得分:1)

您不会在state.ts中从setThings返回任何内容

但是您正在将其分配给App.tsx中的const setThings

<button onClick={setThings}>上,您引用的setThings是您拨打的电话中的undefined返回。

尝试像这样为<button>分配实际功能:

// App.tsx
import { setThings } from "./state";

function App() {
  const setThingsClickHandler = () => {
     setThings([0, 1, 2]);
  };

  return (
    <div>
      <button onClick={setThingsClickHandler}>Set things</button>
    </div>
  );
}

答案 1 :(得分:0)

事实证明,因为我是直接通过两个单独的main.ts标签从HTML文件中导入App.tsx<script>的,所以Parcel为它们创建了两个完全独立的包,这意味着是每个捆绑软件中单独的state对象。

这就是为什么更新一个不会影响另一个的原因。 ?