Reputation: 11
Hi guys would like to know how to fix this issue after updating to React 18 I have a duplicated button due to the useEffect while in StrictMode. Any guide how to unsubscribe to this API call or maybe fix it using a proper cleanup. Thanks in advance.
const paypalbutton = useRef();
useEffect(() => {
const addPayPalScript = async () => {
const { data } = await axios('/api/config/paypal');
script = document.createElement('script');
script.type = 'text/javascript';
script.src = `https://www.paypal.com/sdk/js?client-id=${data}`;
script.async = true;
script.onload = async () => { setSdkReady(true) };
paypalbutton.current.appendChild(script)
};
// inside render()
<li ref={paypalbutton} id="paypal-button" className="row center">
</li>
Upvotes: 1
Views: 1276
Reputation: 19
I fixed it by downgrading to React 17.02
npm uninstall react react-dom
npm install [email protected] [email protected]
Upvotes: -1
Reputation: 8829
React strict mode deliberately runs the useEffect
callback twice to catch misuse of useEffect
, which is what's happening here.
You'll need to do two things:
useEffect(() => {
const controller = new AbortController();
let script
const addPayPalScript = async () => {
const { data } = await axios.get(
'/api/config/paypal',
{ signal: controller.signal }
)
script = document.createElement('script')
script.type = 'text/javascript'
script.src = `https://www.paypal.com/sdk/js?client-id=${data}`
script.async = true
script.onload = () => {
setSdkReady(true)
}
paypalbutton.current.appendChild(script)
completed = true
}
let completed = false
addPayPalScript().then(() => {
completed = true
})
return () => {
controller.abort()
if (completed) {
paypalbutton.current.removeChild(script)
}
}
}, [/* not sure what goes here... */])
Upvotes: 1