comunicar-se com um componente funcional fora de reação
Eu quero ser capaz de me comunicar com meu componente de reação de fora do componente em HTML normal (necessário devido à incorporação de um componente em outro sistema).
Eu estive pesquisando sobre isso e vi conselhos que você pode adicionar componente windowadicionando um ref no elemento renderizado assim:
ReactDOM.render(
<Hello
ref={(element) => {
window.helloComponent = element;
}}
/>,
rootElement
);
Mas para mim não funciona e gera este aviso:
index.js: 27 Aviso: os componentes da função não podem receber refs. As tentativas de acessar este ref falharão. Você pretendia usar React.forwardRef ()?
O componente não é adicionado ao objeto de janela, portanto, a referência não funciona a partir do botão html fora do componente react.
Tenho tentado várias maneiras com createRef () para adicionar à janela, mas não consigo descobrir. Não consigo relacionar os documentos forwardRef () à minha situação atual.
Aqui está o meu código:
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>
Gostaria de saber a técnica certa para acessar alertOne()e alertTwo()de fora de qualquer componente react, apenas de html na mesma página que o componente renderiza.
Respostas
Salvando a função no objeto da janela:
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>
Abordagem orientada a eventos:
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>
Abordagem orientada a eventos com passagem de dados adicionais:
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>
Aqui está um exemplo que criei em que você também pode passar alguns valores usando o padrão de assinatura de publicação de evento em javascript.
https://codesandbox.io/s/react-playground-forked-r7dfn?file=/index.js