与 react 之外的功能组件通信

IT技术 javascript reactjs
2021-05-07 19:48:51

我希望能够在普通 HTML 中从组件外部与我的 react 组件进行通信(由于将组件嵌入到另一个系统中而需要)。

我一直在研究这个,我看到了一些建议,你可以window通过在渲染元素上添加一个 ref来添加组件,如下所示:

  ReactDOM.render(
    <Hello
      ref={(element) => {
        window.helloComponent = element;
      }}
    />,
    rootElement
  );

但对我来说它不起作用并产生这个警告:

index.js:27 警告:不能为函数组件提供引用。尝试访问此引用将失败。你的意思是使用 React.forwardRef() 吗?

该组件不会被添加到 window 对象,因此引用在 react 组件外部的 html 按钮中不起作用。

我一直在尝试使用 createRef() 的各种方法来添加到窗口,但无法弄清楚。我无法将 forwardRef() 文档与我目前的情况联系起来。

这是我的代码:

const rootElement = document.getElementById("root");

if (rootElement) {
  ReactDOM.render(
    <Hello
      ref={(element) => {
        window.helloComponent = element;
      }}
    />,
    rootElement
  );
}

function Hello() {
  function alertOne() {
    alert("hi from 1");
  }
  return (
    <div>
      <h1>Hello, world! </h1> <UpdateButton />
    </div>
  );
}

function UpdateButton() {
  function alertTwo() {
    alert("hi from 2");
  }

  return <button onClick={alertTwo}> Click Me Inside React</button>;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <button onclick="window.helloComponent.alertOne()">
      Click me outside react
    </button>
    <div id="root"></div>

我想知道用于访问alertOne()alertTwo()从任何react组件外部访问的正确技术,仅从组件呈现的同一页面上的 html 即可。

3个回答

将函数保存在 window 对象中:

const rootElement = document.getElementById("root");

if (rootElement) {
  ReactDOM.render(
    <Hello />,
    rootElement
  );
}

function Hello() {

  function alertOne() {
    alert("hi from 1");
  }
  
  window.helloComponentAlert = alertOne;
  
  return (
    <div>
      <h1>Hello, world! </h1> <UpdateButton />
    </div>
  );
}

function UpdateButton() {
  function alertTwo() {
    alert("hi from 2");
  }

  return <button onClick={alertTwo}> Click Me Inside React</button>;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<script>
const handleClick = () => {
  window.helloComponentAlert();
}
</script>

<button onclick="handleClick()">Click me outside react</button>
<div id="root"></div>


事件驱动方法:

const rootElement = document.getElementById("root");

if (rootElement) {
  ReactDOM.render(
    <Hello/>,
    rootElement
  );
}

function Hello() {

  function alertOne() {
    alert("hi from 1");
  }

  React.useEffect(() => {
     window.addEventListener(
       "someEvent",
       alertOne,
       false
    );
  }, []);
  
  return (
    <div>
      <h1>Hello, world! </h1> <UpdateButton />
    </div>
  );
}

function UpdateButton() {
  function alertTwo() {
    alert("hi from 2");
  }

  return <button onClick={alertTwo}> Click Me Inside React</button>;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<script>
const handleClick = () => {
  var someEvent = new Event("someEvent");
  window.dispatchEvent(someEvent);
}
</script>

<button onclick="handleClick()">Click me outside react</button>
<div id="root"></div>


传递额外数据的事件驱动方法:

const rootElement = document.getElementById("root");

if (rootElement) {
  ReactDOM.render(
    <Hello/>,
    rootElement
  );
}

function Hello() {

  function alertOne(e) {
    alert("hi from 1 " + e.detail);
  }

  React.useEffect(() => {
     window.addEventListener(
       "someEvent",
       alertOne,
       false
    );
  }, []);
  
  return (
    <div>
      <h1>Hello, world! </h1> <UpdateButton />
    </div>
  );
}

function UpdateButton() {
  function alertTwo() {
    alert("hi from 2");
  }

  return <button onClick={alertTwo}> Click Me Inside React</button>;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<script>
const handleClick = () => {
  var someEvent = new CustomEvent("someEvent", {detail: "SomeAdditionalData"});
  window.dispatchEvent(someEvent);
}
</script>

<button onclick="handleClick()">Click me outside react</button>
<div id="root"></div>

const rootElement = document.getElementById("root");
window.alertEvent = new Event('alert');

if (rootElement) {
  ReactDOM.render(
    <Hello/>,
    rootElement
  );
}

function Hello() {
  function alertOne() {
    alert("hi from 1");
  }
  window.addEventListener('alert',alertOne);
  return (
    <div>
      <h1>Hello, world! </h1> <UpdateButton />
    </div>
  );
}

function UpdateButton() {
  function alertTwo() {
    alert("hi from 2");
  }

  return <button onClick={alertTwo}> Click Me Inside React</button>;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <button onclick="window.dispatchEvent(window.alertEvent)">
      Click me outside react
    </button>
    <div id="root"></div>

这是我创建的一个示例,您可以在其中使用 javascript 中的事件发布订阅模式传递一些值。

https://codesandbox.io/s/react-playground-forked-r7dfn?file=/index.js