React.js 状态对象在 EventListener 中异步更新/更改,但不会导致组件重新渲染

问题描述 投票:0回答:1

我是 React 新手。我正在尝试将用 VanillaJS 编写的外部库与我的 React 应用程序集成。外部库在其代码的一部分中设置

window.addEventListener()
并对某些对象进行异步更新/更改。

如果我将

state
对象从 React 应用程序传递到此外部方法,我可以观察到当某些相关事件发生时状态对象会发生变化。例如,如果我等待几毫秒,然后将状态打印到 React 应用程序中的控制台,我就可以看到这一点。现在,状态不同了,但组件似乎没有重新渲染。

const myObj = { "counter": 0 }
const [state, SetState] = useState(myObj);

useEffect(() => {
    // console.log(state); -> { "counter": 0 }
    externalLibraryEventListener(state); // externalLibraryEventListener increments myObj["counter"] by 1 asynchronously. 
    // setTimeout(() => {console.log(state)}, 2000) -> { "counter": 1 }
    }
), [state];

在我的研究中,到目前为止,我已经阅读了 React 对数据的浅层和深层副本的不同解释以及不同响应的内容。我不确定这是否是这里发生的事情,但也许这是正确的轨道。我的另一个预感是,它不会重新渲染组件,因为没有任何前端更改(如鼠标单击或填写表单)来更改状态;从 React 应用程序的角度来看,状态对象似乎在内存中发生变化。

最后,我想要的是将一些对象从我的 React 应用程序传递到 VanillaJS 代码,监听状态的变化,然后让我的 React 应用程序在发生此类变化时做出响应。也许考虑到 React 这是不可能的,经过几个小时的尝试,我想我应该在这里问。在提出解决方案时,就我而言,理想的做法是从 React 应用程序端处理所有内容,而无需更改 VanillaJS 代码。

javascript reactjs react-hooks event-listener
1个回答
0
投票

在 React 中,只有一种方法可以导致重新渲染:必须调用 setState。此外,传入 setState 的值必须是新值(由 Object.is 检查标识,类似于

===
)。因此,如果状态是一个对象,则需要将其设置为新对象,而不是改变旧对象。

理想情况下,这个外部库有某种方式告诉您它何时进行更改,然后您可以据此采取行动来调用 setState。像这样的东西(我正在发明外部库代码):

const [counter, setCounter] = useState(0);
useEffect(() => {
  const unsubscribe = externalLibrary.onChange((newValue) => {
    setCounter(newValue);
  });
  return unsubscribe
}, []);

如果图书馆无法告诉您何时发生变化,您就必须发挥创意。如果库正在写入对象的属性,也许您可以使用 setter 函数制作一个对象,并将其用作获取通知的方式。

const [counter, setCounter] = useState(0);
useEffect(() => {
  const interceptor = {
    _counter: 0;
    get counter() {
      return this._counter;
    },
    set counter(newValue) {
      this._counter = newValue;
      setCounter(newValue);
    }
  }
  externalLibraryEventListener(interceptor);
}, []);

您的代码有一个带有 setTimeout 的注释掉的位。这也可能是一个选项:轮询更改,然后设置状态。我认为这不是最好的解决方案,因为它会在您注意到更改之前引入延迟,并且您会遇到这样的情况:您确实努力检查更改但什么也没发生。

在我的示例中,我故意将状态更改为数字而不是对象。如果出于某种原因需要将其保留为对象,请记住每次设置状态时都必须创建一个新对象。改变同一个对象看起来就像什么都没有改变一样。因此,如果您需要使用该对象设置状态,请确保先复制它

setState({ ...stateWhichWasMutated });
© www.soinside.com 2019 - 2024. All rights reserved.