我试图理解为什么这个闭包在从 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
时,它会按预期工作。它更改了state
的things
属性。
但是,当我尝试从 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.ts
和App.tsx
,Parcel 为它们创建了两个完全独立的捆绑包,这意味着每个捆绑包中都有一个单独的state
对象。
这就是为什么更新一个不会影响另一个的原因。 😕