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

Posted

技术标签:

【中文标题】如何使用泛型正确设置 react useState【英文标题】:How to correctly set react useState using generics 【发布时间】:2021-11-11 18:05:00 【问题描述】:

核心问题 - 我在哪里搞砸了我的 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). =&gt; ... 时,我得到了undefined

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

我是否通过不正确地指定类型而弄乱了 useState 的参数?

谢谢!

【问题讨论】:

【参考方案1】:

看起来type definitions for React.useState 有点不安全。对于没有参数的变体,它们不会使用 undefined 增加返回类型。

所以,如果你告诉状态将始终包含IAssetGetManyResponseDto&lt;IAssetResponseDto&gt;,TS 编译器就会相信。

将鼠标悬停在 data 上,查看它有 IAssetGetManyResponseDto&lt;IAssetResponseDto&gt;,而它应该是 IAssetGetManyResponseDto&lt;IAssetResponseDto&gt; | undefined

解决方法:

useState&lt;IAssetGetManyResponseDto&lt;IAssetResponseDto&gt; | undefined&gt;() useState&lt;IAssetGetManyResponseDto&lt;IAssetResponseDto&gt;&gt;(someFunctionalMockOfYourData)

【讨论】:

谢谢@Zbigniew!我一直在尝试执行您提到的第二个选项 useState&lt;IAssetGetManyResponseDto&lt;IAssetResponseDto&gt;&gt;(someFunctionalMockOfYourData) 。我只是不知道如何模拟数据以传递 useState!如果这有助于弄清楚如何在功能上模拟数据,则将类型接口添加到问题中。 经典的“加载”问题。您基本上有 3 个选择 1) 不显示 NewAssetTable,并显示一些“正在加载...”占位符。 2) 确保 NewAssetTabledata=undefined 一起使用 3) 准备“空模拟” ...现在是你的电话,当你有正确的打字时:) 谢谢!但是空的模拟会是什么样子?我如何将它传递给 useState? const [data, setData] = useState&lt;IAssetGetManyResponseDto&lt;IAssetResponseDto&gt;&gt;( items: [], totalCount: number ); ? 是的,看起来items: [], totalCount: 0 适合您的情况。但是,我了解您的应用。您必须决定在数据仍然不可用时显示什么。

以上是关于如何使用泛型正确设置 react useState的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 中正确使用 useState 钩子和 typescript?

在 React 中,如何使用 hook useState 来设置数据?

使用 React 的 useState 钩子时输入可空状态的正确方法

如何使用 Typescript 和 useState 将类型对象设置为 React 的初始值?

如何在 react native 中使用选择器从 redux 状态设置 usestate 的初始值?

React useState导致渲染循环