Проблема с получением графического API-интерфейса при следующем получении js (Ошибка: функциональность React «useContext» недоступна в этой среде.)

Я создал следующее приложение js 14.2.3, и у меня есть конечная точка API Graphql (** которую я заменил на localhost для stackOverflow), и я использую "@apollo/client":"^3.10.3", "graphql":"^16.8.1" для получения данных. Я создал путь к странице продукта «страницы/продукты».

import { useQuery, gql } from "@apollo/client";
import { initializeApollo } from "../lib/apollo-client";

const PRODUCTS_QUERY = gql`
  query Products {
    products(first: 10, channel: "default-channel") {
      edges {
        node {
          id
          name
        }
      }
    }
  }
`;

function Products() {
  const apolloClient = initializeApollo();
  const { data, loading, error } = useQuery(PRODUCTS_QUERY, {
    client: apolloClient,
  });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <div>
      <h1>Products</h1>
      <ul>
        {data &&
          data.products.edges.map(({ node }) => (
            <li key = {node.id}>{node.name}</li>
          ))}
      </ul>
    </div>
  );
}

export default Products;

Я создал файл apollo-client,js.

import { useMemo } from "react";
import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";

let apolloClient;

function createApolloClient() {
  return new ApolloClient({
    ssrMode: typeof window === "undefined",
    link: new HttpLink({
      uri: "http://localhost:8000/graphql/",
    }),
    cache: new InMemoryCache(),
  });
}

export function initializeApollo(initialState = null) {
  const _apolloClient = apolloClient ?? createApolloClient();

  // If your page has Next.js data fetching methods that use Apollo Client, the initial
  state;
  // gets hydrated here
  if (initialState) {
    _apolloClient.cache.restore(initialState);
  }
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === "undefined") return _apolloClient;
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient;

  return _apolloClient;
}

export function useApollo(initialState) {
  const store = useMemo(() => initializeApollo(initialState), [initialState]);
  return store;
}

поэтому, когда я маршрутизирую http://localhost:3000/pages/products

получаю ошибку -

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
625
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, это потому, что компонент <Products /> в настоящее время отображается как серверный компонент. А контексты недоступны для серверных компонентов.

Есть два способа это исправить:

  1. заключается в том, чтобы сделать этот компонент клиентом, добавив "use client" поверх pages/products.

  2. Перепишите компонент, чтобы использовать клиент Apollo напрямую, не полагаясь на перехватчик useQuery. Вотхороший арт, объясняющий, как это сделать.

Пример сырости:

import { gql } from "@apollo/client";
import { initializeApollo } from "../lib/apollo-client";

const PRODUCTS_QUERY = gql`
  query Products {
    products(first: 10, channel: "default-channel") {
      edges {
        node {
          id
          name
        }
      }
    }
  }
`;

async function Products() {
  const apolloClient = initializeApollo();
  const { data } = await apolloClient.query({
    query: PRODUCTS_QUERY,
    context: {},
  });

  return (
    <div>
      <h1>Products</h1>
      <ul>
        {data?.products?.edges?.map(({ node }) => (
          <li key = {node.id}>{node.name}</li>
        ))}
      </ul>
    </div>
  );
}
export default Products;

Недавно я тоже столкнулся с этой ошибкой. Я попробовал первое исправление , данное Ярославом Соболевым, но хотя я использовал «использовать клиент» вверху страницы, это было бесполезно, затем я узнал настоящую причину этой ошибки, которая заключалась в том, что провайдер @apollo/client должен находиться в клиентской среде.

Вот как настроить поставщика в клиентской среде.

Сначала создайте файл Provider.tsx в корневой папке или папке GraphQL.

провайдер.tsx

"use client";
import React, { ReactNode } from "react";
import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";

export const Provider = ({ children }: { children: ReactNode }) => {
  const client = new ApolloClient({
    uri: "http://localhost:5050/graphql",
    cache: new InMemoryCache(),
  });
  return <ApolloProvider client = {client}>{children}</ApolloProvider>;
};

А теперь поместим этого провайдера в файл Layout.tsx.

макет.tsx

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { Provider } from "@/graphql/provider";

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}>
        <Provider>{children}</Provider>
      </body>
    </html>
  );
}

Другие вопросы по теме