skip to Main Content

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>

2

Answers


  1. 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:

    1. Make your asynchronous side effect cancellable; and
    2. Return a cleanup function that will
      • cancel the side-effect if it’s in progress; or
      • undo the side effect if it completed.
    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... */])
    
    Login or Signup to reply.
  2. I fixed it by downgrading to React 17.02

    npm uninstall react react-dom
    
    npm install [email protected] [email protected]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search