TypeScript React Native Flatlist:如何为 renderItem 提供其项目的正确类型?

问题描述 投票:0回答:11

我正在使用 TypeScript 构建一个 React Native 应用程序。

renderItem
抱怨解构项隐式具有
any
类型。我用谷歌搜索并找到了这个问题,并尝试结合React Native的
index.d.ts
包的
@types
中的类型来实现他们在这里教授的内容。

export interface Props {
  emotions: Emotion[];
}

class EmotionsPicker extends PureComponent<Props> {
  keyExtractor = (item, index) => index;
  renderItem = ({ item }) => (
    <ListItem title={item.name} checkmark={item.checked} />
  );

  render() {
    return (
      <FlatList<Emotion>
        keyExtractor={this.keyExtractor}
        renderItem={this.renderItem}
        data={this.props.emotions}
      />
    );
  }
}

不幸的是,这不起作用。我怎样才能给项目指定类型

Emotion

typescript object react-native typescript-typings react-native-flatlist
11个回答
106
投票

我知道这是一个老问题,但谷歌搜索它的人可能仍然会欣赏它。

import { FlatList, ListRenderItem } from 'react-native'
/*
.
.
.
*/
  renderItem: ListRenderItem<Emoticon> = ({ item }) => (
    <ListItem title={item.name} checkmark={item.checked} />
  );

68
投票

我找到了一个解决方案(虽然我不知道它是否理想):

renderItem = ({ item }: { item: Emotion }) => (
  <ListItem title={item.name} checkmark={item.chosen} />
);

28
投票

这是因为在定义

renderItem
时,TypeScript 无法知道它应该作为
renderItem
FlatList
属性。

如果您跳过变量并直接将函数放入 prop 中,TypeScript 应该能够正确推断它:

export interface Props {
  emotions: Emotion[];
}

class EmotionsPicker extends PureComponent<Props> {    
  render() {
    return (
      <FlatList<Emotion>
        keyExtractor={(item, index) => index}
        renderItem={({ item }) => <ListItem title={item.name} checkmark={item.checked} />}
        data={this.props.emotions}
      />
    );
  }
}

18
投票

我找到了一个对我来说非常有效的解决方案:

import { FlatList, ListRenderItemInfo } from 'react-native';


<FlatList
  data={data}
  renderItem={({ item }: ListRenderItemInfo<ItemType>) => (
    <ItemComponent item={item} />
  )}
  keyExtractor={(item: ItemType) => item.id}
/>

7
投票

如果不是内联函数,解构时从 React 导出的正确类型是

ListRenderItemInfo<ItemT>
:

export interface ListRenderItemInfo<ItemT> {
    item: ItemT;

    index: number;

    separators: {
        highlight: () => void;
        unhighlight: () => void;
        updateProps: (select: "leading" | "trailing", newProps: any) => void;
    };
}

4
投票

我觉得这里的答案只解决了如何在更好的情况下修复,在更坏的情况下绕过类型检查,但无法解释为什么它不起作用或者为什么应该按原样输入。

我想更清楚地说明为什么这对大多数人来说会失败,因为即使在官方 wiki 上,它的记录也非常少。


为什么会出现错误:

组件

FlatList
方法不需要您常用来传递(即)标准反应元素构造函数
(props) => JSX.Element
的渲染函数。

无论好坏,

FlatList
renderItem
方法的输入方式如下:

type ListRenderItem<ItemT> = (info: ListRenderItemInfo<ItemT>) =>
   React.ReactElement | null;

这是因为它不需要直接元素构造函数,就像您在大多数 React 模式中习惯的那样标准构造

renderItem
方法。

相反,它需要一个 具有特定类型的回调。这是为了优化目的的内部处理,但在输入时仍然相当笨重。

export interface ListRenderItemInfo<ItemT> {
    item: ItemT;
    index: number;
    separators: {
        highlight: () => void;
        unhighlight: () => void;
        updateProps: (select: 'leading' | 'trailing', newProps: any) => void;
    };
}

输入函数的正确方法

所以这意味着我们应该将我们自己的内部

renderItem
视为回调,以及传递特定
<ItemT>
通用

的特定项目道具
type Props = {
  emotions: Emotion[]
}

// This is the standard React function component
const Item = (({ title, checked }): Emotion) => (
   <ListItem title={title} checked={checked} />
)

// This is the callback for constructing the function component
const renderItem: ListRenderItem<Emotion> = ({ item }: ListRenderItemInfo<Emotion>) => (
   <Item title={item.title} checked={item.checked} />
)

正如您所看到的,乍一看这可能相当令人困惑并且很容易混淆。在

ListRenderItem<T>
告诉打字稿中,我们希望创建一个
T
类型的函数(通用参数),然后构造 (returns) a
Reat.ReactElement | null
。但由于 React 组件本身就是函数,我们仍然需要传递函数来创建一个。这就是混乱和类型错误的根源。

本质上是这样

  1. 创建
    ListRenderItem<T>
  2. 的回调
  3. 仅接受
    ListRenderItemInfo<T>
    的特定 propType 和 prop
    item
  4. 然后需要构造函数
    (props: T) => JSX.Element

而不是传递道具并从中创建元素的标准方式。这也是为什么你(是)收到以下错误:

Property 'property name' does not exist on ListRenderItem<any>

2
投票

使用 TypeScript 使用它来避免类型错误

keyExtractor={(item, index) => index.toString()}

在平面列表中

  <FlatList
       data={list}
       keyExtractor={(item, index) => index.toString()} 
       ....
       />

索引的类型是Number,FlatList需要字符串类型的值作为键。


0
投票

const renderItem = ( {item}:{item:{ id:number, name:string , check:boolean }}) => { return ( ) }


0
投票

找到了解决这个问题的神奇方法


import { ListRenderItemInfo } from 'react-native'

interface PlayerDataStructure {
  imageUrl: string;
  doubleValue: string | number;
  singleValue: string | number;
  isFavorite: boolean;
  name: string;
  thirdRowFirstLabel: string;
  thirdRowSecondLabel: string;
  thirdRowThirdLabel: string;
  thirdRowFourthLabel: string;
  id: number
}

const player: Array<PlayerDataStructure> = [
  { imageUrl: imageUrl, doubleValue: '43', singleValue: '01', isFavorite: true, name: 'Jerome Bell', thirdRowFirstLabel: '19 y', thirdRowSecondLabel: '183 cm', thirdRowThirdLabel: '75 kg', thirdRowFourthLabel: 'Right (2HB)', id: 0 },
  { imageUrl: imageUrl, doubleValue: '43', singleValue: '01', isFavorite: false, name: 'Jerome Bell', thirdRowFirstLabel: '19 y', thirdRowSecondLabel: '183 cm', thirdRowThirdLabel: '75 kg', thirdRowFourthLabel: 'Right (2HB)', id: 1 },
];

  // Render Item
  const renderPlayerData = (object: ListRenderItemInfo<PlayerDataStructure>) => {
    const { item } = object;
    return (
      <PlayerCard imageUrl={item.imageUrl} doubleValue={item.doubleValue} singleValue={item.singleValue} isFavorite={item.isFavorite} name={item.name} thirdRowFirstLabel={item.thirdRowFirstLabel} thirdRowSecondLabel={item.thirdRowSecondLabel} thirdRowThirdLabel={item.thirdRowThirdLabel} thirdRowFourthLabel={item.thirdRowFourthLabel} />
    )
  }

 <FlatList
          numColumns={2}
          data={player}
          keyExtractor={item => item.id.toString()}
          renderItem={renderPlayerData}
          contentContainerStyle={{ gap: PLAYER_CARD_VERTICAL_PADDING, paddingTop: 67 }}
          columnWrapperStyle={{ justifyContent: 'space-between' }}
        />

0
投票

我的问题是我从

FlatList
而不是
react-native-gesture-handler
导入
react-native
。在这种情况下,类型推断无法正常工作,但当我修复导入时,类型推断工作正常。

正确完成后,传递给

renderItem
的项目类型应该可以从 data
 数组的类型推断出
,并且您不必指定/覆盖类型。


-1
投票

这个解决方案非常适合我

interface Props {
    emotions: Emotion[];
}

class EmotionsPicker extends React.Component<Props> {
    render(): React.ReactNode {
        return (
            <FlatList<Emotion>
                data={this.props.emotions}
                keyExtractor={this.keyExtractor}
                renderItem={this.renderItem}
            />
        );
    }

    renderItem: ListRenderItem<Emotion> = (props: ListRenderItemInfo<Emotion>): ReactElement<Emotion, string | JSXElementConstructor<Emotion>> => {};

    keyExtractor = (item: Emotion): string => {};
}
© www.soinside.com 2019 - 2024. All rights reserved.