javascript - .push() 在 Next.js 上不正确地推送两次

标签 javascript reactjs next.js

Cart 组件中 insertToCart() 函数中的 .push() 推送了两次,不知道为什么。由于所有日志都运行一次,我认为它应该可以工作,appendToCart() 工作完美。我有意返回函数的先前值,以免触发整个应用程序的重新渲染。任何帮助将不胜感激。

编辑: saveItem() 被调用两次。

export default function Cart({ children }) {
  const [cart, setCart] = useState([]);
  useEffect(() => {
    setCart(JSON.parse(localStorage.getItem('frentesRosarinos')) || []);
  }, []);
  function insertToCart(product, amount) {
    console.log('insert');
    setCart((pc) => {
      pc.push({ ...product, amount });
      localStorage.setItem('frentesRosarinos', JSON.stringify(pc));
      return pc;
    });
  }
  function appendToCart(id, amount) {
    console.log('append');
    setCart((pc) => {
      const savedItem = pc.find((c) => c.id === id);
      savedItem.amount = amount;
      localStorage.setItem('frentesRosarinos', JSON.stringify(pc));
      return pc;
    });
  }
  return (
    <CartContext.Provider
      value={{ cart, insertToCart, appendToCart }}
    >
      {children}
    </CartContext.Provider>
  );
}
export default function Product({ product, isCart }) {
  const { cart, appendToCart, insertToCart } =
    useContext(CartContext);
  const [addItemClosed, setAddItemClosed] = useState(true);
  const [amount, setAmount] = useState(
    product.amount || cart.find(({ id }) => id === product.id)?.amount || 0,
  );
  const amountToAdd = useRef(0);
  function saveItem(value) {
    setAmount((pa) => {
      const newAmount = parseInt(value) + pa;
      pa === 0 ? insertToCart(product, newAmount) : appendToCart(product.id, newAmount);
      return newAmount;
    });
    amountToAdd.current.value = 0;
  }
  return (
    <div className={styles.container}>
      <div className={styles.addItemsContainer}>
        <p
          onClick={() => setAddItemClosed((ps) => !ps)}
          className={`${styles.addItemsButton} ${addItemClosed ? styles.addBorders : ''}`}
        >
          Agregar más items
        </p>
        <div
          className={`${styles.quantity} ${
            addItemClosed ? styles.addBorders : styles.firstChildHide
          }`}
        >
          <span>Ingrese una cantidad</span>
          <input ref={amountToAdd} type='number' />
        </div>
        <p
          className={`${styles.addOne} ${
            addItemClosed ? styles.addBorders : styles.secondChildHide
          }`}
          onClick={() => saveItem(amountToAdd.current.value)}
        >
          Agregar
        </p>
      </div>
      <div style={{ margin: '10px 0' }}>
        <PressButton action={() => saveItem(1)} size='medium' lightMode>
          {isCart ? 'Agregar otro' : 'Añadir al carrito'}
        </PressButton>
      </div>
    </div>
  );
}

最佳答案

I'm returning the previous value on the functions on purpose, to not trigger a re-render of the whole app. Any help would be much appreciated

你不应该这样做,官方 React 文档说你应该以不可变的方式更新状态,并且你应该遵循这个建议。 也在这里:

pc.push({ ...product, amount });

你再次进行突变,这是不对的。

PS。另外,一般来说,在功能设置状态内调用函数时应小心,以防它们产生副作用,因为在严格模式下,将调用 setter 函数 twice 。在另一个设置状态中调用一个设置状态(如在 setAmount 中调用 setCart)可能会被视为副作用。

关于javascript - .push() 在 Next.js 上不正确地推送两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72254949/

相关文章:

javascript - 下一个JS : async getInitialProps() with AWS S3?

javascript - 动态生成的 <select> 不显示有序列表中的第一项

javascript - 设置输入值不适用于子元素

javascript - ReactJS 渲染函数语法错误

javascript - 无法从 POST 请求获取表单数据

reactjs - Next.js:在静态导出期间将附加属性传递给页面?

javascript - .change() 处理程序使表单需要两次点击才能提交

javascript - Protractor - 等待中继器元素

javascript - 有什么方法可以改变 React js 中渲染的状态吗?

javascript - 如何使用 id React Js 和 Firebase 显示数据