UseContext 不是函数

问题描述 投票:0回答:1

我正在尝试使用我创建的上下文来创建一个非常简单的购物车示例,为此,我创建了一些函数,当我尝试在组件内部使用它时,会弹出错误。
在使用 Context API 方面,我实际上是一个初学者,所以如果有人可以提供帮助,我会非常高兴。
这是我的背景

"use client";
import { createContext, useState, ReactNode } from "react";
import { ShoppingCartProviderProps } from "../types/ShoppingCartProvider";
import { ShoppingCartFunction } from "../types/ShoppingCartFunction";
import { ProductCartItem } from '../types/Product';

export const ShoppingCartContext = createContext({} as ShoppingCartFunction);

export function ShoppingCartProvider({ children }: ShoppingCartProviderProps) {
  const [cartItem, setCartItem] = useState<ProductCartItem[]>([]);

  function getItemQuantity(id: number) {
    return cartItem.find(item => item.id === id)?.quantity || 0;
  }

  function increaseItemQuantity(id: number) {
    setCartItem(currItems => {
      if (currItems.find(item => item.id === id) == null) {
        return [...currItems, { id, quantity: 1 }];
      } else {
        return currItems.map(item => {
          if (item.id === id) {
            return { ...item, quantity: item.quantity + 1 };
          } else {
            return item;
          }
        });
      }
    });
  }

  function decreaseItemQuantity(id: number) {
    setCartItem(currItems => {
      if (currItems.find(item => item.id === id)?.quantity === 1) {
        return currItems.filter(item => item.id !== id);
      } else {
        return currItems.map(item => {
          if (item.id === id) {
            return { ...item, quantity: item.quantity - 1 };
          } else {
            return item;
          }
        });
      }
    });
  }

  function removeFromCart(id: number) {
    setCartItem(currentItems => {
      return currentItems.filter(item => item.id !== id);
    });
  }

  return (
    <ShoppingCartContext.Provider value={{ getItemQuantity, increaseItemQuantity, decreaseItemQuantity, removeFromCart }}>
      {children}
    </ShoppingCartContext.Provider>
  );
}

我如何从 API 获取数据:

export const getData = async () => {

  const res = await fetch('https://fakestoreapi.com/products?limit=5');
  
  if (!res.ok) {
    throw new Error();
  }

  return res.json();
};

以及我尝试在上下文中渲染的组件

import { ShoppingCartContext } from "@/app/context/ShoppingCartContext";
import { getData } from "@/app/data/fetchData";
import { ProductCardDescType } from "@/app/types/Product";
import ProductCard from "@/components/ProductCard/ProductCard";
import { useContext } from "react";

export default async function Store() {
  const post = await getData();

  const { getItemQuantity } = useContext(ShoppingCartContext)

  return (
    <div>
      <h1>Store</h1>
      {post.map((product: ProductCardDescType) => (
        <ProductCard key={product.id} {...product} />
      ))}
    </div>
  );
}

提供者:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import NavBar from "@/components/NavBar/NavBar";
import { ShoppingCartProvider } from "./context/ShoppingCartContext";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <ShoppingCartProvider>
          <NavBar/>
          {children}
        </ShoppingCartProvider>
      </body>
    </html>
  );
}

我想在组件内使用它的上下文,然后使用我为其创建的其他函数。

javascript reactjs typescript next.js provider
1个回答
0
投票

看起来像是客户端与服务器组件问题。

这里有一个链接,next.js 文档明确指出:

由于服务器组件不支持 React 上下文,...

简短的版本是,您正在尝试将“客户端”代码导入到服务器组件中。

具体来说这一行:

 const { getItemQuantity } = useContext(ShoppingCartContext)

要解决此问题,您需要:

  • 使用“useContext”和“use client”标记组件,从而改变您调用的方式

      const post = await getData()
    ,因为它不是服务器组件

  • 使服务器组件导入一些包装您的提供程序的客户端组件。 由于

    ClientComponent
    可以使用“useContext”,因此您可以在该 comoent 中渲染所需内容并将相关数据传递到服务器组件。

import ClientComponent from './client-component'
import ServerComponent from './server-component'
 
// Pages in Next.js are Server Components by default
export default function Page() {
  return (
    <ClientComponent>
      <ServerComponent />
    </ClientComponent>
  )
}

要记住的重要一点是,服务器组件是在服务器上渲染的,因此它们没有交互生命周期效果(useState()、useReducer()、useEffect() 等)

© www.soinside.com 2019 - 2024. All rights reserved.