The right way to use Flatlist + TypeScript + Styled Components in React Native
Everaldo Junior
Posted on February 21, 2022
1. Scenario
Let’s imagine that you need to implement a list of names using TypeScript + Styled Components, like the image below:
2. Dependencies
If you haven’t installed styled-components yet, open your terminal inside your typescript React Native project, copy and paste the lines below:
yarn add styled-components
yarn add @types/styled-components -D
3. Implementing without Styled Components
I am going to implement the list without styled-components, so we can change one part per time.
First, I will define the interface of the objects that are going to be in the list and the data of the items that are going to be rendered
export interface IUser {
id: string;
name: string;
}
const DATA = [
{
id: '1',
name: 'Michael Scott',
},
{
id: '2',
name: 'Jim Halpert',
},
{
id: '3',
name: 'Pam Beesly',
},
{
id: '4',
name: 'Dwight Schrute',
},
{
id: '5',
name: 'Andy Bernard',
},
{
id: '6',
name: 'Ryan Howard',
},
{
id: '7',
name: 'Kelly Kapoor',
},
{
id: '8',
name: 'Toby Flenderson',
},
{
id: '9',
name: 'Stanley Hudson',
},
{
id: '10',
name: 'Phyllis Vance',
},
];
Now I’m going to create the Component that will render each IUser item on the list.
const Item = ({data}: {data: IUser}) => (
<View
style={{
backgroundColor: '#eeeeee',
borderRadius: 10,
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
}}>
<Text style={{fontSize: 24}}>{data.name}</Text>
</View>
);
The first important part here is that you should destruct the data prop that we’re passing to the Item component and type it with the IUser interface.
Finally, I will create the Flatlist component:
const App = () => {
return (
<View style={{flex: 1}}>
<FlatList
data={DATA}
renderItem={({item}) => <Item data={item} />}
keyExtractor={(item: IUser) => item.id}
/>
</View>
);
};
4. Adding Styled Components
Now, we are ready to refactor these components using styled-components.
First, I will create a file and name it styles.ts
Now, I will create a style for each component that we created previously.
import {FlatList} from 'react-native';
import styled from 'styled-components/native';
import {IUser} from './App';
export const Container = styled.View`
flex: 1;
`;
export const ItemContainer = styled.View`
background-color: #eeeeee;
border-radius: 10px;
padding: 20px;
margin-vertical: 8px;
margin-horizontal: 16px;
`;
export const ItemName = styled.Text`
font-size: 24px;
`;
export const UsersList = styled.FlatList`
padding: 20px;
`;
After that, we can replace the components with inline styles with the isolated styles that we just created.
const Item = ({data}: {data: IUser}) => (
<ItemContainer>
<ItemName>{data.name}</ItemName>
</ItemContainer>
);
const App = () => {
const renderItem: ListRenderItem<IUser> = ({item}) => <Item data={item} />;
return (
<Container>
<UsersList
data={DATA}
renderItem={renderItem}
keyExtractor={(item: IUser) => item.id}
/>
</Container>
);
};
But you will see that Typescript will fire an error in your styled-Component created Flatlist
That’s because you have to declare the type of data that we’re passing to the Flatlist to the styled-component flatlist.
So go to your styles.ts file and change the UsersList style from:
export const UsersList = styled.FlatList`
padding: 20px;
`;
To:
export const UsersList = styled(FlatList as new () => FlatList<IUser>)`
padding: 20px;
`;
5. Conclusion and Final Result
Using TypeScript + Flatlists + Styled Components can be tricky sometimes, but I hope that this tutorial helps you somehow.
That’s our final App.tsx file:
import React from 'react';
import {ListRenderItem} from 'react-native';
import {Container, ItemContainer, ItemName, UsersList} from './styles';
export interface IUser {
id: string;
name: string;
}
const DATA = [
{
id: '1',
name: 'Michael Scott',
},
{
id: '2',
name: 'Jim Halpert',
},
{
id: '3',
name: 'Pam Beesly',
},
{
id: '4',
name: 'Dwight Schrute',
},
{
id: '5',
name: 'Andy Bernard',
},
{
id: '6',
name: 'Ryan Howard',
},
{
id: '7',
name: 'Kelly Kapoor',
},
{
id: '8',
name: 'Toby Flenderson',
},
{
id: '9',
name: 'Stanley Hudson',
},
{
id: '10',
name: 'Phyllis Vance',
},
];
const Item = ({data}: {data: IUser}) => (
<ItemContainer>
<ItemName>{data.name}</ItemName>
</ItemContainer>
);
const App = () => {
const renderItem: ListRenderItem<IUser> = ({item}) => <Item data={item} />;
return (
<Container>
<UsersList
data={DATA}
renderItem={renderItem}
keyExtractor={(item: IUser) => item.id}
/>
</Container>
);
};
export default App;
And that’s our final styles.ts file:
import {FlatList} from 'react-native';
import styled from 'styled-components/native';
import {IUser} from './App';
export const Container = styled.SafeAreaView`
flex: 1;
`;
export const ItemContainer = styled.View`
background-color: #eeeeee;
border-radius: 10px;
padding: 20px;
margin-vertical: 8px;
margin-horizontal: 16px;
`;
export const ItemName = styled.Text`
font-size: 24px;
`;
export const UsersList = styled(FlatList as new () => FlatList<IUser>)`
padding: 20px;
`;
And here’s the tutorial repository on GitHub.
Posted on February 21, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 21, 2022