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



我试图理解为什么这个闭包在从 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>
);
}

当从非 React 代码调用setThings时,它会按预期工作。它更改了statethings属性。

但是,当我尝试从 React 组件调用它时,就像在 App.tsx 中一样,它根本不起作用。调试表明,当从App内部调用setThings时,它认为state.things是一个空数组[],它是初始化的值,即使state.things已经包含了很多项目。

这似乎暗示 React 以某种方式将复制版本的setThings与复制版本的state一起使用。这怎么可能?它不应该作为一个简单的闭包并引用真正的state吗?


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

编辑:我在为这个问题🤦 ♂️编写组件代码时犯了一个错误。我现在修复了它。我问题中的问题仍在发生。

编辑2:

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

画布中的每个"行星"都由数组中的一个项目表示。每个行星的坐标和加速度在每一帧上都会发生变化。当行星碰撞时setThings与变化的行星阵列一起调用。这需要发生,因为多个行星可以相互"碰撞"并组合成一个,从而导致一个state.things数组,删除了 2 个项目并添加了 1 个新项目。

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

您不会从 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>
);
}

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

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

最新更新