import { useEffect } from "react";
const GoogleTranslate = () => {
useEffect(() => {
let addScript = document.createElement("script");
addScript.setAttribute(
"src",
"//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"
);
document.body.appendChild(addScript);
window.googleTranslateElementInit = googleTranslateElementInit;
}, []);
const googleTranslateElementInit = () => {
return new window.google.translate.TranslateElement(
{
pageLanguage: "en",
layout: google.translate.TranslateElement.InlineLayout.BUTTON,
},
"google_translate_element"
);
};
return <div id="google_translate_element"></div>;
};
export default GoogleTranslate;
Here is my Component. I have used in a single page. But instead of once I am getting two separate instance of google translate button.
So, I want to know how to render only once this button.
Here is the UI image
Double Google translate button bug
CodePudding user response:
useEffect
may run twice despite an empty dependency array in multiple circumstances (for example, if a parent component is re-rendering, or if you have React StrictMode enabled).
Hence, you are probably creating 2 elements inside useEffect
.
You could analyze your code and check for potential unwanted re-renders or simply replace useEffect
with this useEffectOnce
hook:
import { useEffect, useRef, useState } from 'react';
export const useEffectOnce = (effect: () => void | (() => void)) => {
const effectFn = useRef<() => void | (() => void)>(effect);
const destroyFn = useRef<void | (() => void)>();
const effectCalled = useRef(false);
const rendered = useRef(false);
const [, setVal] = useState<number>(0);
if (effectCalled.current) {
rendered.current = true;
}
useEffect(() => {
if (!effectCalled.current) {
destroyFn.current = effectFn.current();
effectCalled.current = true;
}
setVal(val => val 1);
return () => {
if (!rendered.current) {
return;
}
if (destroyFn.current) {
destroyFn.current();
}
};
}, []);
};
Just create a file with this code, and import and use it instead of useEffect
.