javascript - 重新加载 Commerce.js 结帐页面时出现错误( react 教程)

标签 javascript reactjs e-commerce commerce commerce.js

我目前正在为 Commerce.js Api 编写 React.js 结帐教程。

当我单击购物车中的结帐按钮时,它会将我带到结帐页面,并按应有的方式生成结帐 token ,但我注意到当我重新加载结帐页面时,控制台显示以下错误: Image of errors .

这是结账页面的代码:

import React, { useEffect, useState } from 'react';
import { commerce } from '../../lib/commerce';
import './styles.css';

const Checkout = ({ cart }) => {

    const [checkoutToken, setCheckoutToken] = useState({});

    useEffect(() => {
        generateCheckoutToken();
    }, [])

    const generateCheckoutToken = () => {
        if (cart.line_items.length) {
            commerce.checkout.generateToken(cart.id, { type: 'cart' })
                .then((token) => {
                    setCheckoutToken(token);
                    console.log(checkoutToken);
                }).catch((error) => {
                    console.log('There was an error in generating a token', error);
                });
        }
    }

    return (
        <div>
            Checkout
        </div>
    )
}

export default Checkout

我认为这与使用 generateCheckoutToken() 函数之前购物车未加载有关,但我不明白如何解决该问题。

这是 App.js:

import { useEffect, useState } from 'react';
import { commerce } from './lib/commerce';
import { Routes, Route } from 'react-router-dom';
import ProductsList from './components/ProductList/ProductsList';
import Cart from './components/Cart/Cart';
import Checkout from './components/Checkout/Checkout';
import './App.css';

function App() {

  const [products, setProducts] = useState([]);
  const [cart, setCart] = useState({});
  const [prductLoading, setProductLoading] = useState(false);
  const [cartBtn, setCartBtn] = useState(false);

  const fetchProducts = () => {
    commerce.products.list().then((products) => {
      setProducts(products.data);
      setProductLoading(false);
    }).catch((error) => {
      console.log('There was an error fetching the products', error);
    });
  }

  const fetchCart = () => {
    commerce.cart.retrieve().then((cart) => {
      setCart(cart)
    }).catch((error) => {
      console.error('There was an error fetching the cart', error);
    });
  }

  const handleAddToCart = (productId, quantity) => {
    commerce.cart.add(productId, quantity).then((item) => {
      setCart(item.cart)
    }).catch((error) => {
      console.error('There was an error adding the item to the cart', error);
    });
  }

  const handleUpdateCartQty = (lineItemId, quantity) => {
    commerce.cart.update(lineItemId, { quantity }).then((resp) => {
      setCart(resp.cart)
    }).catch((error) => {
      console.log('There was an error updating the cart items', error);
    });
  }

  const handleRemoveFromCart = (lineItemId) => {
    commerce.cart.remove(lineItemId).then((resp) => {
      setCart(resp.cart)
    }).catch((error) => {
      console.error('There was an error removing the item from the cart', error);
    });
  }

  const handleEmptyCart = () => {
    commerce.cart.empty().then((resp) => {
      setCart(resp.cart)
    }).catch((error) => {
      console.error('There was an error emptying the cart', error);
    });
  }

  const handleCloseCart = () => {
    setCartBtn(false);
  }

  useEffect(() => {
    setProductLoading(true);
    fetchProducts();
    fetchCart();
  }, [])

  // console.log(cart);

  return (
    <div className="App">
      <Routes>
        <Route
          exact
          path='/'
          element={
            <div className='home'>
              <div className={`cart-button ${cartBtn && 'cartOpen'}`}>
                {cartBtn ?
                  <Cart
                    cart={cart}
                    onUpdateCartQty={handleUpdateCartQty}
                    onRemoveFromCart={handleRemoveFromCart}
                    onEmptyCart={handleEmptyCart}
                    closeCartBtn={handleCloseCart}
                  />
                  :
                  <p onClick={() => setCartBtn(true)}>Open cart</p>
                }
              </div>
              {prductLoading ?
                'Loading...'
                :
                <ProductsList
                  products={products}
                  onAddToCart={handleAddToCart}
                />
              }
            </div>
          }
        />
        <Route
          exact
          path='/checkout'
          element={
            <Checkout 
              cart={cart}
            />
          }
        />
      </Routes>
    </div>
  );
}

export default App;

如果有人能告诉我我缺少什么,我将不胜感激,感谢您的帮助!!

最佳答案

问题

当您在 App 状态下初始化 cart 时,它是一个空对象{}。它作为 Prop 传递给 Checkout

一旦 Checkout 安装,它就会调用 generateCheckoutToken,它会尝试读取 cart.line_items.length。如果这种情况发生在父级中调用 fetchCart 之前,则 cart 是一个空对象,没有 line_items 可供计数。这是一个竞争条件。

一种解决方案

一种解决方案是在 useEffect 中监听 cart 的变化,并且仅在 cart 时调用 generateCheckoutToken > 有 line_items。这可能不支持您 future 的设计目标,但应该可以解决此错误。

// Checkout
useEffect(() => {
  if(cart.line_items) { 
    generateCheckoutToken();
  }
}, [cart])

关于javascript - 重新加载 Commerce.js 结帐页面时出现错误( react 教程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69920262/

相关文章:

javascript - JS 串联

php - 使用 PHP/SQL 通过单击事件处理程序实现动态 JavaScript 变量

javascript - 将 React 模板放入一个全局变量的属性中

php - 如何在 opencart 中创建自定义管理页面?

javascript - Adblock 正在阻止 iframe 重定向 - 如何检测?

javascript - 如何停止在页面重新加载时从 jQuery 函数中删除附加类

reactjs - 使用react-router时参数列表后缺少 )

javascript - React.js 中游戏币的结账按钮

e-commerce - 如何启用第三方支付网关(Shopify 目前不支持)

statistics - 如何衡量界面更改是否提高或降低了可用性?