使用React钩子同时从2个不同组件更新全局变量

huangapple go评论56阅读模式
英文:

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 &#39;reactn&#39;;
const initStore = () =&gt; {
setGlobal({
globalArray: [],
});
};
export default initStore;

component-number-one.js

import React,{useEffect, } from &#39;react&#39;;
// works just like useState but makes the variables accessible anywhere
import { useGlobal, } from &#39;reactn&#39;;
// Just a clone util, clones stuff
import { clone } from &#39;../../../utils/clone&#39;;
const ComponentNumberOne = () =&gt; {
const [globalArray, setGlobalArray] = useGlobal(&#39;globalArray&#39;); 
useEffect(() =&gt; {
// Only want this to run on mount
let newGlobalArray = clone(globalArray); // Problem is here, doesn&#39;t know globalArray has an updated value
newGlobalArray.push(&quot;ComponentNumberOne&quot;);
setGlobalArray(newGlobalArray);
// Only want this to run on dismount
return () =&gt; {
let newGlobalArray = clone(globalArray);  // Possibly problem here too
let index = newGlobalArray.indexOf(&quot;ComponentNumberOne&quot;);
newGlobalArray.splice(index,1);
setGlobalArray(newGlobalArray);
}
},[]);
return (
&lt;div className=&quot;ComponentNumberOne&quot;&gt;
ComponentNumberOne stuff
&lt;/div&gt;
);
};
export default ComponentNumberOne;

component-number-two.js

import React,{useEffect, } from &#39;react&#39;;
// works just like useState but makes the variables accessible anywhere
import { useGlobal, } from &#39;reactn&#39;;
// Just a clone util, clones stuff
import { clone } from &#39;../../../utils/clone&#39;;
const ComponentNumberTwo = () =&gt; {
const [globalArray, setGlobalArray] = useGlobal(&#39;globalArray&#39;); 
useEffect(() =&gt; {
// Only want this to run on mount
let newGlobalArray = clone(globalArray); // Problem is here, doesn&#39;t know globalArray has an updated value
newGlobalArray.push(&quot;ComponentNumberTwo&quot;);
setGlobalArray(newGlobalArray);
// Only want this to run on dismount
return () =&gt; {
let newGlobalArray = clone(globalArray); // Possibly problem here too
let index = newGlobalArray.indexOf(&quot;ComponentNumberTwo&quot;);
newGlobalArray.splice(index,1);
setGlobalArray(newGlobalArray);
}
},[]);
return (
&lt;div className=&quot;ComponentNumberTwo&quot;&gt;
ComponentNumberOne stuff
&lt;/div&gt;
);
};
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(() =&gt; {
if( !globalArray.includes(&quot;ComponentNumberTwo&quot;) ){
setGlobalArray([
...globalArray,
&quot;ComponentNumberTwo&quot;
]);
};
}, [ globalArray ]);

huangapple
  • 本文由 发表于 2023年3月15日 21:27:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75745358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定