使用 TypeScript 反应 FlatList

Posted

技术标签:

【中文标题】使用 TypeScript 反应 FlatList【英文标题】:React FlatList with TypeScript 【发布时间】:2020-11-14 16:44:30 【问题描述】:

TypeScript 真的很棒,只是目前我觉得我为 TypeScript 工作比为我工作更多。

我有一个在轮播中呈现餐厅结果的 FlatList。

 const renderRestaurantRows = ( item ) => (
    <Carousel
      id=item.id
      name=item.name
    />
  );
  const renderBottomSheetRestaurantList = () => (
    <View style=[styles.listView,  height: topSnapPoint ]>
      <FlatList
        data=restaurants
        keyExtractor=(item) => `row-$item.id`
        renderItem=renderRestaurantRows
      />
    </View>
  );

TypeScript 抱怨 itemBinding element 'item' implicitly has an 'any' type - 是有道理的。所以我试着告诉它会发生什么:

  interface RestaurantItem 
    item: 
      id: string;
      name: string;
    ;
  
  const renderRestaurantRows = ( item : RestaurantItem) => (
    <Carousel
      id=item.id
      name=item.name
    />
  );

但随后 TS 抱怨 data=restaurants]Type 'Restaurant[]' is not assignable to type 'readonly id: string; name: string; imageUrl: string; rating: number; reviews: number; 以及大量其他信息。

是否有人可以分享解决方案并解释将来如何为其他类似案例找到这样的解决方案?

更新

restaurants 是从自定义挂钩中获取的。它被定义为一个 Restaurant 对象数组:

interface Restaurant 
  id: string;
  name: string;

export default function useRestaurantSearch() 
  const [restaurants, setRestaurants] = useState<Restaurant[] | null>(null);
  ...

更新 2

各位大大感谢cmets,根据两个建议,我重写了代码:

import useRestaurantSearch from '../hooks/useRestaurantSearch';
export default function RestaurantPage() 
  const renderRestaurantRows = ( item : Restaurant) => (
    <Carousel
      id=item.id
      name=item.name
    />
  );
  const renderBottomSheetRestaurantList = () => (
    <View style=[styles.listView,  height: topSnapPoint ]>
      <FlatList
        data=restaurants
        keyExtractor=(item) => `row-$item.id`
        renderItem=renderRestaurantRows
      />
    </View>
  );

这一次, item : RestaurantCannot find name 'Restaurant' 出现错误。这并不奇怪,因为 Restaurant 是在外部挂钩文件 ../hooks/useRestaurantSearch 中定义的。我需要以某种方式导入它吗?

更新 3

玩了几个小时后,我到了这一点:

  const renderRestaurantRows = (result:  item: Restaurant ) => 
    return <Carousel ...result.item />;
  ;
  const renderBottomSheetRestaurantList = () => (
    <View style=[styles.listView,  height: topSnapPoint ]>
      <FlatList
        data=restaurants
        keyExtractor=(item) => `row-$item.id`
        renderItem=renderRestaurantRows
      />
    </View>
  );

renderItem 生成一个对象,该对象包含item 键下的每个餐厅数据。例如,其中一个对象可能是:


  "index": 18,
  "item": Object 
    "coordinates": Object 
      "latitude": 123,
      "longitude": -123,
    ,
    "id": "dfg987fshjsdfh",
    "name": "Yummy Food",
  ,
  "separators": Object 
    "highlight": [Function highlight],
    "unhighlight": [Function unhighlight],
    "updateProps": [Function updateProps],
  ,

当我传递result 对象时,我可以让TS 知道对象内部的item 并将其转换为Restaurant 类型。我用 (result: item: Restaurant ). However, when I try to directly destructure the resultobject with( item : Restaurant)it gives me the errorProperty 'item' does not exist on type 'Restaurant'`来做到这一点。知道为什么吗?

【问题讨论】:

你是如何定义restaurants的类型的?尝试用 RestaurantItem[] 注释这个数组 @Drag13 请查看我更新的问题。 您正在获取 Restaurant 类型,但想要处理 RestaurantItem 类型。它们不兼容,TypeScript 对此抱怨。您应该使用相同类型或餐厅类型的子集 我会说你找到了解决方案,只需导入类型就可以了) @ben 我相信如果你要解构你需要这样做: item : item: Restaurant 【参考方案1】:

尝试导入 ListRenderItem 并输入接收函数的 const:

import  ListRenderItem  from 'react-native';
...
const renderRestaurantRows: ListRenderItem<Restaurant> = ( item ) => (
  <Carousel
    id=item.id
    name=item.name
  />
);

你真正从 renderItems 得到的参数是:

ItemT 是您的类型,Restaurant

【讨论】:

我觉得这确实是更好的方法。 这解决了我的问题。唯一的事情是你需要确保 renderRestaurantRows 返回 JSX 否则 Typescript 仍然会给你一个错误。【参考方案2】:

假设要渲染的项目是Movie

    _renderItem(info: ListRenderItemInfo<Movie>): ReactElement<Movie> 
        return <MovieTile movie=info.item />;
    

    render() 
        let movies = this.props.movies;

        return <FlatList
            data=movies
            horizontal=true
            renderItem=this._renderItem
            keyExtractor=(item, i) => item.id.toString()
            />;
    

【讨论】:

嗨。您如何将该代码转换为功能组件“样式”?谢谢 您可以将内部函数定义为renderItem

以上是关于使用 TypeScript 反应 FlatList的主要内容,如果未能解决你的问题,请参考以下文章

带有 Typescript 和样式化组件的 RN FlatList

如何反应原生重新渲染 Flatlist?

反应原生 Flatlist 导航

反应本机打字稿如何键入 FlatList

反应原生 |循环渲染 FlatList 的项目

如何在反应原生中改变 <​​FlatList/> 的高度?