如何使用泛型正确设置react useState

人气:1,012 发布:2022-10-16 标签: generics typescript reactjs use-effect use-state

问题描述

核心问题-我在哪里搞砸了我的useState

  const [data, setData] = useState<IAssetGetManyResponseDto<IAssetResponseDto>>();

所以我作为道具发送下来的data对象是undefined

我的(正常运行)API调用如下

export const getAllAssets = async (
 
): Promise<IAssetGetManyResponseDto<IAssetResponseDto>> => {
  console.log("get all assets ran in api.ts!")
  const response = await amsApiClient.get(ASSET_ENDPOINT(),
  {
    params: {
      limit: 1000
    }
  }
  );
  console.log("logging response data "+JSON.stringify(response.data))
  return response.data;
};

以下是正在使用的类型:

export interface IAssetGetManyResponseDto<T> {
  items: T[];
  totalCount: number;
}

export interface IAssetResponseDto {
  id: string | null;
  name: string | null;
  type: string | null;
  url: string | null;
  // metadata: IMetadataObj| null;
  tags: Array<string> | null;
  thumbnailImageURL: string | null;
  createdAt: number | null;
  updatedAt: number | null;
}

下面是进行调用的组件,以显示上下文

export const AssetManagementTable = () => {

  const [data, setData] = useState<IAssetGetManyResponseDto<IAssetResponseDto>>();

  const getAssets = async () => {

    console.log("getAssets ran!")

    const assets = await getAllAssets();
    console.log("logging data from asset managment table " + data)
    console.log("logging assets from asset managment table " + assets)
    setData(assets)
  }

  useEffect(() => {
    getAssets()
  }, []);

  return (

    <div>
      <NewAssetTable items={data} />
    </div>
  );
};

在我的应用程序中的其他地方,当我向下传递道具并引用props.items.map((item: any). => {...时,我得到了undefined

更确切地说,TypeError: Cannot read properties of undefined (reading 'map')

我是否因为不正确地指定类型而搞乱了useState的参数?

谢谢!

推荐答案

看起来type definitionsforReact.useState有点不安全。对于没有参数的变量,它们不会使用undefined扩充返回类型。

因此,如果您告诉该状态将始终包含IAssetGetManyResponseDto<IAssetResponseDto>,TS编译器会相信它。

将鼠标悬停在data上以查看它具有IAssetGetManyResponseDto<IAssetResponseDto>,而它应该是IAssetGetManyResponseDto<IAssetResponseDto> | undefined

解决方法:

useState<IAssetGetManyResponseDto<IAssetResponseDto> | undefined>() useState<IAssetGetManyResponseDto<IAssetResponseDto>>(someFunctionalMockOfYourData)

516