【问题标题】:How to Fix Duplicated Paypal Button in React Strict Mode如何在 React 严格模式下修复重复的 Paypal 按钮
【发布时间】:2022-10-19 18:07:02
【问题描述】:

大家好,我想知道在更新到 React 18 后如何解决这个问题我有一个重复的 由于在 StrictMode 下的 useEffect 按钮。任何指南如何取消订阅此 API 调用 或者也许使用适当的清理来修复它。提前致谢。

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>

【问题讨论】:

    标签: reactjs use-effect paypal-sandbox android-strictmode paypal-buttons


    【解决方案1】:

    React 严格模式故意运行useEffect 回调两次以捕获滥用useEffect,这就是这里发生的事情。

    你需要做两件事:

    1. 使您的异步副作用可取消;和
    2. 返回一个清理函数,它将
      • 取消正在进行的副作用;或者
      • 如果完成,请撤消副作用。
      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... */])
      

    【讨论】:

    • 嗨史蒂夫非常感谢您的回复。我已经尝试实施更改,但不幸的是,贝宝​​按钮闪烁然后消失。我检查了控制台,出现了一些错误,例如不推荐使用 findDOMNode 以及一些关于某些 VM 元素被破坏的错误。在此之后,我尝试将 useEffect 中的已完成变量等局部变量设置为 useRef 变量以保持初始渲染的值,但这次仍然存在一些问题 Uncaught TypeError: Cannot read properties of undefined (reading 'removeChild') .我会尝试更多并更新你。
    • 嗨史蒂夫,正如你所分享的那样,我得到了确切的实施。错误 1.) react-dom.development.js:86 警告:在 StrictMode 中不推荐使用 findDOMNode。 findDOMNode 被传递了一个在 StrictMode 中的 e 实例。相反,直接将 ref 添加到要引用的元素。在此处了解有关安全使用 refs 的更多信息:reactjs.org/link/strict-mode-find-node at div at e 2.) OrderDetails.js:66 Uncaught (in promise) Cancel {message: 'canceled'} addPayPalScript 3. VM19 js:2 unhandled_error {err: 'Error: zoid 销毁所有组件 4. VM19Uncaught Error: zoid destroy all
    • 我还将尝试使用这些实现按钮的另一种实现方式。希望它有效。从“@paypal/react-paypal-js”导入 { PayPalScriptProvider, PayPalButtons, usePayPalScriptReducer };
    • 嗨,史蒂夫终于让代码工作了。我实际上引用了包含插入按钮的错误父元素。无论如何,非常感谢您的帮助!
    • 嗨,史蒂夫,在摆弄不同的解决方案期间,我能够在加载按钮的页面的初始渲染中显示按钮一次,但是如果我卸载该页面/屏幕转到另一个屏幕/页面然后回到它我会居然又看到了两个按钮。该代码实际上可能正在工作,但问题可能是初始订阅潜伏在某个地方,即使卸载发生并且实际上并未被删除。不确定如何在 useEffect 的返回中正确清理它。
    【解决方案2】:

    我通过降级到 React 17.02 来修复它

    npm uninstall react react-dom
    
    npm install react@17.0.2 react-dom@17.0.2
    

    【讨论】:

      猜你喜欢
      • 2012-04-18
      • 2020-10-27
      • 2017-01-07
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 2019-03-20
      • 2018-09-02
      • 2016-01-27
      相关资源
      最近更新 更多