You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS+TypeScript中使用Context时Dispatch类型报错求助

问题

在NextJS + TypeScript项目中使用React Context时,为Context默认值设置useState的setter函数时出现类型错误:
Property 'Dispatch' does not exist on type 'typeof import("d:/NextJS/crypto-tracker/node_modules/@types/react/index.d.ts")'
移除Dispatch后,SetStateAction也会报相同错误。

相关代码与配置如下:

Context文件代码

"use client";
import React, { createContext, useEffect, useState, Dispatch } from "react";

export const CryptoContext = createContext({
  allCoins: [],
  currency: { name: "usd", symbol: "$" },
  setCurrency: React.Dispatch<
    React.SetStateAction<{ name: "usd"; symbol: "$" }>
  >,
});

const CryptoContextProvider = ({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) => {
  const [allCoins, setAllCoins] = useState([]);
  const [currency, setCurrency] = useState({ name: "usd", symbol: "$" });
  const fetchAllCoins = async () => {
    const options = {
      method: "GET",
      headers: {
        accept: "application/json",
        "x-cg-demo-api-key": "",
      },
    };

    fetch(
      `https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency.name}`,
      options
    )
      .then((res) => res.json())
      .then((res) => setAllCoins(res))
      .catch((err) => console.error(err));
  };
  useEffect(() => {
    fetchAllCoins();
  }, [currency]);
  const contextValue = { allCoins, currency, setCurrency };
  return (
    <CryptoContext.Provider value={contextValue}>
      {children}
    </CryptoContext.Provider>
  );
};

export default CryptoContextProvider;

package.json配置

{
  "name": "crypto-tracker",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev --turbopack",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "15.1.7",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@eslint/eslintrc": "^3",
    "@types/node": "^20",
    "@types/react": "^19.0.10",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "15.1.7",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "typescript": "^5"
  }
}

tsconfig.json配置

{
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

已尝试重装react、@types/react、react-dom,切换TypeScript版本至5.7.3,错误仍未解决。


解决方案

1. 修正Context类型与默认值定义

核心问题是:你将类型引用作为createContext的默认值,而非实际运行时值;同时错误地通过React.前缀访问已导入的类型。修改后的代码如下:

"use client";
import React, { createContext, useEffect, useState, Dispatch, SetStateAction } from "react";

// 先定义Context的完整类型
type CryptoContextType = {
  allCoins: any[]; // 建议替换为具体的硬币类型,比如Coin[]
  currency: { name: "usd"; symbol: "$" };
  setCurrency: Dispatch<SetStateAction<{ name: "usd"; symbol: "$" }>>;
};

// 提供合法的默认值(空函数作为setter的兜底实现)
export const CryptoContext = createContext<CryptoContextType>({
  allCoins: [],
  currency: { name: "usd", symbol: "$" },
  setCurrency: () => {}, // 必须传入实际函数,不能用类型引用
});

// Provider部分代码保持不变
const CryptoContextProvider = ({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) => {
  const [allCoins, setAllCoins] = useState<any[]>([]);
  const [currency, setCurrency] = useState({ name: "usd", symbol: "$" });
  const fetchAllCoins = async () => {
    const options = {
      method: "GET",
      headers: {
        accept: "application/json",
        "x-cg-demo-api-key": "",
      },
    };

    fetch(
      `https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency.name}`,
      options
    )
      .then((res) => res.json())
      .then((res) => setAllCoins(res))
      .catch((err) => console.error(err));
  };
  useEffect(() => {
    fetchAllCoins();
  }, [currency]);
  const contextValue = { allCoins, currency, setCurrency };
  return (
    <CryptoContext.Provider value={contextValue}>
      {children}
    </CryptoContext.Provider>
  );
};

export default CryptoContextProvider;

2. 错误原因解析

  • createContext的参数需要运行时可用的值,你之前传入的React.Dispatch<...>是TypeScript类型,不属于运行时代码,因此报错。
  • 你已经从react包导入了Dispatch和SetStateAction,无需再通过React.前缀访问,这在React 19的类型定义中会导致找不到对应属性。

3. 额外优化建议

为allCoins定义具体类型,提升代码安全性:

// 定义硬币数据的类型
type Coin = {
  id: string;
  name: string;
  symbol: string;
  current_price: number;
  image: string;
  // 根据API返回的字段补充其他属性
};

// 替换useState的泛型
const [allCoins, setAllCoins] = useState<Coin[]>([]);
type CryptoContextType = {
  allCoins: Coin[];
  // ...其他属性
};

内容的提问来源于stack exchange,提问作者Swapnodip Chakrabarti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:17:09