更新 useContext 中的值时,组件不会重新呈现

Jor*_*Paz 9 reactjs gatsby react-context

我正在使用 React 的上下文 api 来存储一组项目。有一个组件可以通过 useContext() 访问这个数组并显示数组的长度。还有另一个组件可以访问该函数以通过 useContext 更新此数组。将项目添加到数组时,组件不会重新渲染以反映数组的新长度。当我导航到应用程序中的另一个页面时,组件会重新呈现并反映数组的当前长度。每当上下文中的数组发生变化时,我都需要组件重新渲染。

我曾尝试使用 Context.Consumer 而不是 useContext 但是当数组更改时它仍然不会重新呈现。

//orderContext.js//

import React, { createContext, useState } from "react"

const OrderContext = createContext({
  addToOrder: () => {},
  products: [],
})

const OrderProvider = ({ children }) => {
  const [products, setProducts] = useState([])

  const addToOrder = (idToAdd, quantityToAdd = 1) => {
    let newProducts = products
    newProducts[newProducts.length] = {
      id: idToAdd,
      quantity: quantityToAdd,
    }
    setProducts(newProducts)
  }

  return (
    <OrderContext.Provider
      value={{
        addToOrder,
        products,
      }}
    >
      {children}
    </OrderContext.Provider>
  )
}

export default OrderContext
export { OrderProvider }
Run Code Online (Sandbox Code Playgroud)
//addToCartButton.js//

import React, { useContext } from "react"
import OrderContext from "../../../context/orderContext"

export default ({ price, productId }) => {
  const { addToOrder } = useContext(OrderContext)

  return (
    <button onClick={() => addToOrder(productId, 1)}>
      <span>${price}</span>
    </button>
  )
}

Run Code Online (Sandbox Code Playgroud)
//cart.js//

import React, { useContext, useState, useEffect } from "react"
import OrderContext from "../../context/orderContext"

export default () => {
  const { products } = useContext(OrderContext)
  return <span>{products.length}</span>
}
Run Code Online (Sandbox Code Playgroud)
//gatsby-browser.js//

import React from "react"
import { OrderProvider } from "./src/context/orderContext"
export const wrapRootElement = ({ element }) => (
   <OrderProvider>{element}</OrderProvider>
)
Run Code Online (Sandbox Code Playgroud)

我希望当数组更新时,购物车组件会显示数组的新长度,但它会保持不变,直到我导航到另一个页面时重新呈现组件。每次更新上下文中的数组时,我都需要它重新渲染。

sko*_*ovy 17

问题很可能是您正在改变数组(而不是设置新数组),因此 React 使用浅等式将数组视为相同。

更改addOrder分配新数组的方法应该可以解决此问题:

const addToOrder = (idToAdd, quantityToAdd = 1) =>
  setProducts([
    ...products,
    {
      id: idToAdd,
      quantity: quantityToAdd
    }
  ]);
Run Code Online (Sandbox Code Playgroud)

编辑上下文数组

  • `let newProducts = products` - 这是一个引用赋值。对“newProducts”所做的任何修改也会影响“products”。为了避免改变原始数组,请始终创建一个副本 - `let newProducts = [ ...products ]`。不过,在您的情况下,我不会推荐这种方法,因为这是不必要的步骤。只需遵循@skovy 的建议即可:) (2认同)

mut*_*toe 6

正如@skovy所说,如果你想改变原始数组,有基于他的答案的更优雅的解决方案。

setProducts(prevState => {
  prevState[0].id = newId
  return [...prevState]
})
Run Code Online (Sandbox Code Playgroud)