user3887366
user3887366

Reputation: 2624

React native typescript how to type FlatList

I don't find the way to type a FlatList in react native

export interface Category {
  id: string;
  title: string;
  bg: string;
}
export const CATEGORIES: Category[] = [
  { id: "c1", title: "Italian", bg: "#f5428d" }
];


const Item = ({ data }: { data: Category }) => (
  <View style={styles.item}>
    <Text style={styles.title}>{data.title}</Text>
  </View>
);
const CategoriesScreen = ({ navigation }: CategoriesScreenProps) => {
  const renderItem  = ({
    data,
  }: {
    data: Category;
  }) => <Item data={data} />;
  return (
    <FlatList
      data={CATEGORIES}
      keyExtractor={(item) => item.id}
      renderItem={renderItem}
      numColumns={2}
    ></FlatList>
  );
};

I've got this error in renderItem props:

No overload matches this call. Overload 1 of 2, '(props: FlatListProps | Readonly<FlatListProps>): FlatList', gave the following error. Type '({ data, }: { data: Category; }) => JSX.Element' is not assignable to type 'ListRenderItem'. Types of parameters '__0' and 'info' are incompatible. Property 'data' is missing in type 'ListRenderItemInfo' but required in type '{ data: Category; }'. Overload 2 of 2, '(props: FlatListProps, context: any): FlatList', gave the following error. Type '({ data, }: { data: Category; }) => JSX.Element' is not assignable to type 'ListRenderItem

What's wrong, please?

Upvotes: 4

Views: 9394

Answers (5)

Rayhan
Rayhan

Reputation: 1

The flatList component passes each item in your array as a variable with the name item to the renderItem prop. So you need to replace data with item, like this:

const renderItem  = ({item}: {item: Category}) => <Item data={item} />;

<FlatList
    data={CATEGORIES}
    keyExtractor={(item) => item.id}
    renderItem={renderItem}
    numColumns={2}
></FlatList>

Upvotes: 0

aderossett
aderossett

Reputation: 111

I know this is super old, but I think I might have the solution that you were ultimately looking for. I think we must be walking through the same tutorial, because I ran into this exact same problem with the exact same typing issue.

If I'm understanding this correctly, ultimately what everyone else has said here is technically correct; the data that's used by the FlatList is going to be a ListRenderItem<T>. However, the individual data items wrapped by ListRenderItem that are passed to the function you define for the renderItem prop is actually of type ListRenderItemInfo<T>. So, you should be able to type your function parameters like I've typed the itemData parameter below:

import { FlatList, ListRenderItemInfo } from "react-native"
import { CategoryGridTile } from "irrelevant"
import { CATEGORIES } from "irrelevant"
import Category from "irrelevant"

export const CategoriesScreen: React.FC = () => {
    return <FlatList
        data={CATEGORIES}
        keyExtractor={(item) => item.id}
        renderItem={renderCategoryItem}
    />
}

const renderCategoryItem = (itemData: ListRenderItemInfo<Category>) => {
    return <CategoryGridTile title={itemData.item.title} color={itemData.item.color} />
}

Where Category is:

class Category {
  constructor(id, title, color) {
    this.id = id
    this.title = title
    this.color = color
  }
}

I found this by digging into the definition of FlatList and its types:

export interface ListRenderItemInfo<ItemT> {
    item: ItemT;

    index: number;

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

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

I'm sure you've long passed this issue, but hopefully it helps someone else dealing with the same typing problem.

Upvotes: 11

EmilM
EmilM

Reputation: 137

You can try to write like this:

<FlatList<Category>
      data={CATEGORIES}
      .....

Upvotes: 0

Yilmaz
Yilmaz

Reputation: 49681

I think here the error desribes what went wrond :" Property 'data' is missing in type 'ListRenderItemInfo' but required in type '{ data: Category; }'."

  const renderItem  = ({data}: {data: Category}) => <Item data={data} />

You need to pass an object which has a "data" property, but you did not.

 <FlatList
  data={CATEGORIES}
  keyExtractor={(item) => item.id}
  renderItem= {renderItem} // {(receivesArg)=>renderItem(passArg)}
  numColumns={2}
></FlatList>

or

<FlatList
      data={CATEGORIES}
      keyExtractor={(item) => item.id}
      // import {ReactElement} from "react"
      renderItem= {({ data }:data: Category;}):ReactElement => <Item data={data} />}
      numColumns={2}
    ></FlatList>

Upvotes: 2

Lailton Batista
Lailton Batista

Reputation: 21

renderItem has the interface ListRenderItem< ItemT > , so the "data" param doesn't exist, because ListRenderItem only knows "item", "index" and "separator". Try to replace its ItemT with your data.

How do you do that? It's simple:

1st - import the ListRenderItem interface from react-native,

import { ListRenderItem } from 'react-native';

2nd - type the constant receiving the renderItem function instead of the params, replacing its "ItemT" with your item interface:

const renderItem: ListRenderItem<Category> = ({ item }) => (
   <Item data={item} />
)

That's it!! Wanna check it out the code? here it is: expo snack

Upvotes: 2

Related Questions