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

React+TypeScript全局状态数组更新报错:使用useContext管理GeoJSONItem数组时的类型不兼容问题

React+TypeScript全局状态数组更新报错:使用useContext管理GeoJSONItem数组时的类型不兼容问题

我来帮你分析下问题所在,你遇到的TypeScript错误主要是Context里的setter类型定义不对,还有数据构造的问题,咱们一步步解决:

问题根源拆解

  1. Setter类型定义错误:你在GeoJSONContextType里把setGeoJSONList定义成了(selected: GeoJSONItem[]) => void,但React的useState setter其实支持两种调用方式——直接传新数组,或者传一个接收prevState的函数返回新数组(也就是你想用的函数式更新)。这个类型限制导致TypeScript认为你传的函数不符合参数要求。
  2. 状态初始化不完整:visable的useState初始化是useState<boolean>(),没有默认值,所以它的类型是boolean | undefined,但你定义的setVisable参数是boolean,这会导致类型不兼容。
  3. 数据类型不匹配:你在组件里直接把json as FeatureCollection加到数组里,这不符合GeoJSONItem的类型要求——GeoJSONItem需要id、name、visable、color这些元数据,不是单纯的FeatureCollection对象。

解决方案

1. 修正Context的类型定义,使用React内置类型

把setter类型改成React标准的Dispatch<SetStateAction<T>>,这样就能支持函数式更新:

import { createContext, useContext, useState, Dispatch, SetStateAction } from "react";
import { FeatureCollection } from "geojson";

export type GeoJSONItem = {
  id: string;
  name: string;
  visable: boolean;
  color: string;
  geoJSON: FeatureCollection;
};

type GeoJSONContextType = {
  geoJSONList: GeoJSONItem[];
  setGeoJSONList: Dispatch<SetStateAction<GeoJSONItem[]>>; // 修正为支持函数式更新的类型
  setVisable: Dispatch<SetStateAction<boolean>>; // 同步修正setVisable的类型
};

2. 给visable状态添加默认值

在Provider里给visable一个明确的默认值,避免undefined类型问题:

const GeoJSONProvider: React.FC<Props> = ({ children }) => {
  const [geoJSONList, setGeoJSONList] = useState<GeoJSONItem[]>([]);
  const [visable, setVisable] = useState<boolean>(false); // 添加默认值false
  return (
    <GeoJSONContext.Provider value={{ geoJSONList, setGeoJSONList, setVisable }}>
      {children}
    </GeoJSONContext.Provider>
  );
};

3. 正确构造GeoJSONItem对象

不能直接把FeatureCollection塞进数组,要包装成符合GeoJSONItem类型的对象:

// 假设你有这些元数据和GeoJSON数据
const newLayerId = "layer-001"; // 可以用uuid生成唯一ID
const newLayerName = "My Custom Layer";
const newLayerColor = "#2ecc71";
const rawGeoJSON: FeatureCollection = json; // 假设json是合法的FeatureCollection

// 构造符合类型要求的GeoJSONItem
const newGeoJSONItem: GeoJSONItem = {
  id: newLayerId,
  name: newLayerName,
  visable: true,
  color: newLayerColor,
  geoJSON: rawGeoJSON
};

4. 正确调用函数式更新

现在类型匹配了,你可以安全地用函数式更新添加单个或多个项:

const { setGeoJSONList } = useGeoJSONContext();

// 添加单个项
setGeoJSONList(prevList => [...prevList, newGeoJSONItem]);

// 添加多个项
const multipleNewItems: GeoJSONItem[] = [/* 多个构造好的GeoJSONItem */];
setGeoJSONList(prevList => [...prevList, ...multipleNewItems]);

完整修改后的GeoJSONContext.tsx

import { createContext, useContext, useState, Dispatch, SetStateAction } from "react";
import { FeatureCollection } from "geojson";

export type GeoJSONItem = {
  id: string;
  name: string;
  visable: boolean;
  color: string;
  geoJSON: FeatureCollection;
};

type GeoJSONContextType = {
  geoJSONList: GeoJSONItem[];
  setGeoJSONList: Dispatch<SetStateAction<GeoJSONItem[]>>;
  setVisable: Dispatch<SetStateAction<boolean>>;
};

const GeoJSONContext = createContext<GeoJSONContextType>({
  geoJSONList: [],
  setGeoJSONList: () => {},
  setVisable: () => {}
});

export const useGeoJSONContext = () => useContext(GeoJSONContext);

type Props = {
  children?: React.ReactNode;
};

const GeoJSONProvider: React.FC<Props> = ({ children }) => {
  const [geoJSONList, setGeoJSONList] = useState<GeoJSONItem[]>([]);
  const [visable, setVisable] = useState<boolean>(false);

  return (
    <GeoJSONContext.Provider value={{ geoJSONList, setGeoJSONList, setVisable }}>
      {children}
    </GeoJSONContext.Provider>
  );
};

export default GeoJSONProvider;

这样修改后,TypeScript的错误应该就消失了,而且你可以遵循React不可变更新的原则来修改全局数组,不用再用不符合规范的push方法。

备注:内容来源于stack exchange,提问作者Even Lauvsnes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 12:14:07