英文:
Updating a global variable from 2 different components simultaneously using react hooks
问题
以下是您要翻译的内容:
我有一个全局变量,它是一个数组。
在两个不同的组件中,它们在挂载时同时向数组中添加一个元素。但为了向数组中添加一个元素,它们需要克隆当前的数组并添加到其中。由于它们同时挂载,当它们克隆数组时,数组是空的。因此,只有一个元素添加到数组中。
我该如何使用 useEffect 在挂载时运行插入的代码一次,并在卸载时运行返回的代码,读取一个可能会更改的全局变量。
这里是一个示例:
store.js
import { setGlobal } from 'reactn';
const initStore = () => {
setGlobal({
globalArray: [],
});
};
export default initStore;
component-number-one.js
import React, { useEffect } from 'react';
// 就像 useState 一样工作,但可以使变量在任何地方都可以访问
import { useGlobal } from 'reactn';
// 只是一个克隆工具,克隆东西
import { clone } from '../../../utils/clone';
const ComponentNumberOne = () => {
const [globalArray, setGlobalArray] = useGlobal('globalArray');
useEffect(() => {
// 只想在挂载时运行此代码
let newGlobalArray = clone(globalArray); // 问题在这里,不知道 globalArray 是否有更新的值
newGlobalArray.push("ComponentNumberOne");
setGlobalArray(newGlobalArray);
// 只想在卸载时运行此代码
return () => {
let newGlobalArray = clone(globalArray); // 可能在这里也有问题
let index = newGlobalArray.indexOf("ComponentNumberOne");
newGlobalArray.splice(index, 1);
setGlobalArray(newGlobalArray);
}
}, []);
return (
<div className="ComponentNumberOne">
ComponentNumberOne stuff
</div>
);
};
export default ComponentNumberOne;
component-number-two.js
import React, { useEffect } from 'react';
// 就像 useState 一样工作,但可以使变量在任何地方都可以访问
import { useGlobal } from 'reactn';
// 只是一个克隆工具,克隆东西
import { clone } from '../../../utils/clone';
const ComponentNumberTwo = () => {
const [globalArray, setGlobalArray] = useGlobal('globalArray');
useEffect(() => {
// 只想在挂载时运行此代码
let newGlobalArray = clone(globalArray); // 问题在这里,不知道 globalArray 是否有更新的值
newGlobalArray.push("ComponentNumberTwo");
setGlobalArray(newGlobalArray);
// 只想在卸载时运行此代码
return () => {
let newGlobalArray = clone(globalArray); // 可能在这里也有问题
let index = newGlobalArray.indexOf("ComponentNumberTwo");
newGlobalArray.splice(index, 1);
setGlobalArray(newGlobalArray);
}
}, []);
return (
<div className="ComponentNumberTwo">
ComponentNumberOne stuff
</div>
);
};
export default ComponentNumberTwo;
希望这可以帮助您。如果您有任何其他问题,欢迎提出。
英文:
I have a global variable that is an array.
In 2 different components they add an element to the array simultaneously on mount. But in order to add an element to the array they need to clone the current one & add to it. Since they're mounting simultaneously, the array is empty when they clone it. So only one element is added to the array.
How can I use useEffect to run the inserted code once on mount & run the return code on dismount reading a global variable that can change.
here's an example
store.js
import { setGlobal } from 'reactn';
const initStore = () => {
setGlobal({
globalArray: [],
});
};
export default initStore;
component-number-one.js
import React,{useEffect, } from 'react';
// works just like useState but makes the variables accessible anywhere
import { useGlobal, } from 'reactn';
// Just a clone util, clones stuff
import { clone } from '../../../utils/clone';
const ComponentNumberOne = () => {
const [globalArray, setGlobalArray] = useGlobal('globalArray');
useEffect(() => {
// Only want this to run on mount
let newGlobalArray = clone(globalArray); // Problem is here, doesn't know globalArray has an updated value
newGlobalArray.push("ComponentNumberOne");
setGlobalArray(newGlobalArray);
// Only want this to run on dismount
return () => {
let newGlobalArray = clone(globalArray); // Possibly problem here too
let index = newGlobalArray.indexOf("ComponentNumberOne");
newGlobalArray.splice(index,1);
setGlobalArray(newGlobalArray);
}
},[]);
return (
<div className="ComponentNumberOne">
ComponentNumberOne stuff
</div>
);
};
export default ComponentNumberOne;
component-number-two.js
import React,{useEffect, } from 'react';
// works just like useState but makes the variables accessible anywhere
import { useGlobal, } from 'reactn';
// Just a clone util, clones stuff
import { clone } from '../../../utils/clone';
const ComponentNumberTwo = () => {
const [globalArray, setGlobalArray] = useGlobal('globalArray');
useEffect(() => {
// Only want this to run on mount
let newGlobalArray = clone(globalArray); // Problem is here, doesn't know globalArray has an updated value
newGlobalArray.push("ComponentNumberTwo");
setGlobalArray(newGlobalArray);
// Only want this to run on dismount
return () => {
let newGlobalArray = clone(globalArray); // Possibly problem here too
let index = newGlobalArray.indexOf("ComponentNumberTwo");
newGlobalArray.splice(index,1);
setGlobalArray(newGlobalArray);
}
},[]);
return (
<div className="ComponentNumberTwo">
ComponentNumberOne stuff
</div>
);
};
export default ComponentNumberTwo;
答案1
得分: 2
useEffect
应该在其依赖数组中包含 globalArray
。
当然,仅仅将 globalArray
放在依赖数组中会破坏你的代码。
真正的问题是你的代码表现得“命令式”,即“如果组件已挂载,就向数组中添加一个项目”。这不是 React 应该使用的方式。
而不是告诉 React 何时执行某事,你应该告诉 React 你期望的状态是什么。即更新数组以表示所期望的状态,例如:
useEffect(() => {
if( !globalArray.includes("ComponentNumberTwo") ){
setGlobalArray([
...globalArray,
"ComponentNumberTwo"
]);
};
}, [ globalArray ]);
英文:
The useEffect
should have globalArray
in its dependencies array.
Of course, just putting globalArray
in the dependencies breaks your code.
The actual problem is that your code behaves "imperatively", i.e. "if the component is mounted, add an item to the array. That is not the way React is supposed to be used.
Instead of telling React when to do something, you should tell React what state you expect. I.e. update the array to represent the desired state, e.g.:
useEffect(() => {
if( !globalArray.includes("ComponentNumberTwo") ){
setGlobalArray([
...globalArray,
"ComponentNumberTwo"
]);
};
}, [ globalArray ]);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论