使用 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 抱怨 item
和 Binding 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 : Restaurant
和 Cannot 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 error
Property '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的主要内容,如果未能解决你的问题,请参考以下文章