首页 > 解决方案 > Next.js useContext TypeError:无法解构'Object(...)(...)',因为它未定义

问题描述

我尝试使用useContext在 Next.js 应用程序中更改光标的状态,但出现此错误:

TypeError: Cannot destructure 'Object(...)(...)' as it is undefined.

状态应更改为isActive:当悬停按钮时为 true

我的上下文提供者:

import { createContext, useState } from "react";

export const CursorContext = createContext();

const CursorContextProvider = ({ children }) => {
  const [cursor, setCursor] = useState({ active: false });
  return (
    <CursorContext.Provider value={[cursor, setCursor]}>
      {children}
    </CursorContext.Provider>
  );
};

export default CursorContextProvider;

在应用程序中:

import App from "next/app";
import Head from "next/head";
import Layout from "../components/Layout";
import CursorContextProvider from "../components/CursorContextProvider";
import Cursor from "../components/Cursor";
import { getCategories } from "../utils/api";
import "../styles/index.css";
import "../styles/style.scss";

const MyApp = ({ Component, pageProps, children }) => {
  return (
    <Layout categories={pageProps.categories}>
      <Head>
        <link rel="preconnect" href="https://app.snipcart.com" />
        <link rel="preconnect" href="https://cdn.snipcart.com" />
        <link
          rel="stylesheet"
          href="https://cdn.snipcart.com/themes/v3.0.16/default/snipcart.css"
        />
        <script src="https://cdn.snipcart.com/themes/v3.0.16/default/snipcart.js" />
      </Head>
      <CursorContextProvider>
      <Cursor />
      {children}
    </CursorContextProvider> 
      <Component {...pageProps} />
    </Layout>
  );
};

// getInitialProps disables automatic static optimization for pages that don't
// have getStaticProps. So [[...slug]] pages still get SSG.
// Hopefully we can replace this with getStaticProps once this issue is fixed:
// https://github.com/vercel/next.js/discussions/10949
MyApp.getInitialProps = async (ctx) => {
  // Calls page's `getInitialProps` and fills `appProps.pageProps`
  const appProps = await App.getInitialProps(ctx);
  // Fetch global site settings from Strapi
  const categories = await getCategories();
  // Pass the data to our page via props
  return { ...appProps, pageProps: { categories, path: ctx.pathname } };
};

export default MyApp;

这是我的光标组件:

import React, { useContext } from "react";
import useMousePosition from "./useMousePosition";
import { CursorContext } from "./CursorContextProvider";

const Cursor = () => {
  const { clientX, clientY } = useMousePosition();
  const [cursor] = useContext(CursorContext);
  return (
    <div 
      style={{ 
        position: "fixed",
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        zIndex: 9999,
        pointerEvents: "none"
      }}
    >
      <svg
        width={50}
        height={50}
        viewBox="0 0 50 50"
        style={{
          position: "absolute",
          left: clientX,
          top: clientY,
          transform: `translate(-50%, -50%) scale(${cursor.active ? 2.5 : 1})`,
          stroke: cursor.active ? "black" : "white",
          strokeWidth: 1,
          fill: cursor.active ? "rgba(255,255,255,.5)" : "black",
          transition: "transform .2s ease-in-out",
        }}
      >
        <circle
          cx="25"
          cy="25"
          r="8"
        />
      </svg>
    </div>
  );
};
export default Cursor;

和一个测试按钮组件:

import { useContext, useCallback } from "react";
import { CursorContext } from "./CursorContextProvider";
const Button = () => {
  const [, setCursor] = useContext(CursorContext);

  const toggleCursor = useCallback(() => {
    setCursor(({ active }) => ({ active: !active }));
  });
  return (
    <button
      type="button"
      style={{ padding: "1rem" }}
      onMouseEnter={toggleCursor}
      onMouseLeave={toggleCursor}
    >
      HOVER ME
    </button>
  );
};
export default Button;

你看到我在哪里做错了 setState undefined 吗?

标签: javascriptreact-hooksnext.jssetstateuse-context

解决方案


这很可能是由于您CursorContextProvider没有包装Button正在使用的组件。尝试将它移动到返回的 JSX 的顶部App

const MyApp = ({ Component, pageProps, children }) => {
    return (
        <CursorContextProvider>
            <Layout categories={pageProps.categories}>
                //...
            </Layout>
        </CursorContextProvider> 
    );
};

推荐阅读