【问题标题】:Third party API needs to access state in React app第三方 API 需要访问 React 应用中的状态
【发布时间】:2020-12-03 14:09:31
【问题描述】:

我们有一个 React 应用程序,它与第三方库进行通信以进行电话集成。每当有人调用时,第三方库都会在 React 应用程序内触发回调函数。到目前为止一切正常,但现在这个回调函数需要访问当前状态,这似乎会造成问题。这个回调函数内部的状态,似乎总是在初始值,永远不会更新。

我这里做了一个小沙盒来描述问题:https://codesandbox.io/s/vigorous-panini-0kge6?file=/src/App.js

在沙箱中,当我单击“内部增加”时,计数器值会正确更新。但是,已将相同的函数添加为对 ThirdPartyApi 的回调,当我单击“外部增加”时会调用该函数。当我这样做时,计数器值将恢复为 useState 中的默认值。

如何让第三个库知道 React 内部的状态更新?

App.js:

import React, { useState, useEffect } from "react";
import ThirdPartyApi from "./third-party-api";
import "./styles.css";

let api = new ThirdPartyApi();

export default function App() {
  const [counter, setCounter] = useState(5);

  const increaseCounter = () => {
    setCounter(counter + 1);
    console.log(counter);
  };

  useEffect(() => {
    api.registerCallback(increaseCounter);
  }, []);

  return (
    <div className="App">
      <p>
        <button onClick={() => increaseCounter()}>Internal increase</button>
      </p>

      <p>
        <button onClick={() => api.triggerCallback()}>External increase</button>
      </p>
    </div>
  );
}

第三方-api.js:

export default class ThirdPartyApi {
  registerCallback(callback) {
    this.callback = callback;
  }

  triggerCallback() {
    this.callback();
  }
}

【问题讨论】:

  • 请将最小可行代码直接添加到问题中,谢谢。
  • 我已经更新了问题。
  • 请注意,与沙盒不同,我们无法控制“真实”场景中的第三方代码...

标签: javascript reactjs


【解决方案1】:

您需要通过React's useCallbackincreaseCounter() 包装到回调中。 事实上,api.registerCallback() 会因此而重新渲染,重置 counter

您可以了解有关此行为的更多信息here

import React, { useState, useCallback, useEffect } from "react";
import ReactDOM from "react-dom";

class ThirdPartyApi {
  registerCallback(callback) {
    this.callback = callback;
  }

  triggerCallback() {
    this.callback();
  }
}

let api = new ThirdPartyApi();

function App() {
  const [counter, setCounter] = useState(5);

  const increaseCounter = useCallback(() => {
    setCounter(counter + 1);
    console.log(counter);
  }, [counter]);

  useEffect(() => {
    api.registerCallback(increaseCounter);
  }, [increaseCounter]);

  return (
    <div className="App">
      <p>
        <button onClick={() => increaseCounter()}>Internal increase</button>
      </p>

      <p>
        <button onClick={() => api.triggerCallback()}>External increase</button>
      </p>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);

【讨论】:

  • 请记住,这将在每次更新时注册回调。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 2019-10-09
  • 1970-01-01
  • 2018-06-03
  • 2012-03-20
  • 1970-01-01
相关资源
最近更新 更多