Reputation: 14786
I'm building a React Native app using TypeScript. I'm trying to use a SectionList
. I followed the docs, and here is my code:
renderSectionHeader = ({ section: { title } }: { section: { title: string } }) => (
<ListItem title={title} />
);
render() {
const { sections } = this.props;
return (
<SafeAreaView style={styles.container}>
<SectionList
keyExtractor={this.keyExtractor}
sections={[
{title: 'Title1', data: ['item1', 'item2']},
{title: 'Title2', data: ['item3', 'item4']},
{title: 'Title3', data: ['item5', 'item6']},
]}
renderItem={this.renderItem}
renderSectionHeader={this.renderSectionHeader}
/>
</SafeAreaView>
);
}
But the line renderSectionHeader={this.renderSectionHeader}
throws the following TSLint Error:
[ts]
Type '({ section: { title } }: { section: { title: string; }; }) => Element' is not assignable to type '(info: { section: SectionListData<any>; }) => ReactElement<any> | null'.
Types of parameters '__0' and 'info' are incompatible.
Type '{ section: SectionListData<any>; }' is not assignable to type '{ section: { title: string; }; }'.
Types of property 'section' are incompatible.
Type 'SectionListData<any>' is not assignable to type '{ title: string; }'.
Property 'title' is missing in type 'SectionListData<any>'. [2322]
Are the types of SectionList
broken? Or is the example wrong? Or am I doing something wrong?
Upvotes: 19
Views: 15764
Reputation: 4804
const sections = [
{title: 'Title1', data: ['item1', 'item2']},
{title: 'Title2', data: ['item3', 'item4']},
{title: 'Title3', data: ['item5', 'item6']},
];
First you need to define the Section
type and the Item
type:
type Item = string;
type Section = {
title: string;
data: Item[];
};
Now you need to define your renderItem
function:
const renderItem: SectionListRenderItem<Item, Section> = ({item}) => {
// return component here
};
Upvotes: 7
Reputation: 111
import React from 'react';
import {SectionList, SectionListData, SectionListRenderItem, SectionListRenderItemInfo, Text} from 'react-native';
export type Item = string; // <-- Change me
export type Section = {
title: string; // <-- Change me
data: readonly Item[];
}
type ListProps = {
sections: SectionListData<Item, Section>[],
}
type RenderSectionHeaderArgs = {
section: SectionListData<Item, Section>
}
const renderSectionItem: SectionListRenderItem<Item> = ({item}) => {
console.log(item);
return <Text>{item}</Text>;
};
const renderSectionHeader = ({section: {title, data}}: RenderSectionHeaderArgs) => {
console.log({title, data});
return <Text>{title}</Text>;
};
const List: React.FC<ListProps> = ({sections}) => {
return (
<SectionList
sections={sections}
renderItem={renderSectionItem}
renderSectionHeader={renderSectionHeader}
/>
);
};
export default List;
Upvotes: 0
Reputation: 81
This one worked for me:
import type { SectionListData } from 'react-native';
interface Section {
title?: string;
data: readonly any[];
}
type SectionHeader = (info: { section: SectionListData<YOUR_ARRAY_TYPE, Section> }) => React.ReactElement;
const renderSectionHeader: SectionHeader = ({ section: { title } }) => {
return YOUR_HEADER_COMPONENT;
};
Upvotes: 4
Reputation: 1357
if you know what types you're using and it's only to avoid the warning you could do:
sections={sections as any[]}
Upvotes: -6
Reputation: 71
This is the SectionListData
declaration, so you just need to remove the title
property, and replace it with key
, then TSLint Error
will disappear.
export interface SectionBase<ItemT> {
data: ReadonlyArray<ItemT>;
key?: string;
renderItem?: SectionListRenderItem<ItemT>;
ItemSeparatorComponent?: React.ComponentType<any> | null;
keyExtractor?: (item: ItemT, index: number) => string;
}
export interface SectionListData<ItemT> extends SectionBase<ItemT> {
[key: string]: any;
}
Upvotes: 0
Reputation: 35
interface Data {
...
}
const MySectionList = SectionList as SectionList<Data>;
<MySectionList
...
/>
worked for me
Upvotes: 1
Reputation: 323
I'a new to TypeScript so this question might not be the best but you can check React Native types here: React Native Types github
In line 4243 for now you can see this:
renderSectionHeader?: (info: { section: SectionListData<ItemT> }) => React.ReactElement<any> | null;
This mean that renderSectionHeader property require a function with one argument which is an object with section field of SectionListData<ItemT>
type.
To get rid of error that you posted, you can do something like this:
renderSectionHeader = ({ section: { title } }: { section: { title: string } }): React.ReactElement<any>=> (<ListItem title={title} />)
render() {
const { sections } = this.props;
return (
<SafeAreaView style={styles.container}>
<SectionList
keyExtractor={this.keyExtractor}
sections={[
{title: 'Title1', data: ['item1', 'item2']},
{title: 'Title2', data: ['item3', 'item4']},
{title: 'Title3', data: ['item5', 'item6']},
]}
renderItem={this.renderItem}
renderSectionHeader={({section}: {section: SectionListData<string[]>}) => this.renderSectionHeader(section)}
/>
</SafeAreaView>
);
}
Hope this is correct and will help you.
EDIT: If you dont want to provide types during props passing this renderHeader method will be errorless:
renderSectionHeader = ({ section }: {section: SectionListData<string[]>}): ReactElement<any> | null => (<Text>{section.title}</Text>)
Upvotes: 1