React Native - Routing with IDs
This lesson is part of a series on React Native.
Step 15 - Routing for Books
Add a file named books.js to your project folder and put this into it:
export const bookData = [
{
id: "1",
title: "The Pragmatic Programmer",
author: "Andrew Hunt & David Thomas",
summary: "A classic book about practical software development principles."
},
{
id: "2",
title: "Clean Code",
author: "Robert C. Martin",
summary: "Focuses on writing readable, maintainable, and clean code."
},
{
id: "3",
title: "You Don't Know JS",
author: "Kyle Simpson",
summary: "A deep dive into how JavaScript really works."
}
];
Add these Stack.Screen elements to app/_layout.js:
<Stack.Screen name="books/index" options={{ title: "Books"}} />
<Stack.Screen name="books/[id]" options={{ title: "Book Details"}} />
Add this to the CustomScreen element in app/index.jsx:
<Link href="/books">Books</Link>
Add a folder named books to the app folder.
Then add a file named index.jsx to the books folder, and put this into it:
import { StyleSheet, Text, View } from 'react-native'
import {Link} from 'expo-router'
import {useEffect, useState} from 'react'
import {bookData} from '../../books'
import CustomScreen from '../../components/CustomScreen'
import CustomText from '../../components/CustomText'
const index = () => {
const [books, setBooks] = useState([]);
useEffect(() => {
// We would normally do an API call here to get the books
setBooks(bookData)
}, [])
return (
<CustomScreen>
{books.map( b => <Link key={b.id} href={"/books/" + b.id}>
<CustomText title>{b.title}</CustomText>
</Link>)}
</CustomScreen>
)
}
export default index
const styles = StyleSheet.create({})
Run the app and navigate to the books index page.
We should really use a FlatList instead of generating all the Link elements with books.map(). Don't forget to import FlatList, then update the returned JSX to look like this:
<CustomScreen>
<FlatList
data={books}
renderItem={({item}) => <Link key={item.index} href={"/books/" + item.id}><CustomText>{item.title}</CustomText></Link>} />
</CustomScreen>
Creating a Book Details component
Create a file named [id].jsx in the books folder.
Note that what you put inside the square brackets makes anything that comes after /books/ a param that you can access from your code.
Put this code inside the [id].jsx file:
import { View, Text, StyleSheet } from "react-native";
import { useLocalSearchParams } from "expo-router";
import CustomScreen from "../../components/CustomScreen";
import CustomText from "../../components/CustomText";
const BookDetails = () => {
const {id} = useLocalSearchParams();
return (
<CustomScreen>
<CustomText>BOOK: {id}</CustomText>
</CustomScreen>
)
}
export default BookDetails
const styles = StyleSheet.create({})
Run the app, and notice how the book id is displayed in the BookDetails component.
Modify the [id].jsx file to look like this:
import { View, Text, StyleSheet } from "react-native";
import { useLocalSearchParams } from "expo-router";
import CustomScreen from "../../components/CustomScreen";
import CustomText from "../../components/CustomText";
// Add these imports
import {bookData} from '../../books'
import {useState, useEffect} from 'react'
const BookDetails = () => {
const {id} = useLocalSearchParams();
// Add book state (initialize to an empyt obj)
const [book, setBook] = useState({});
// Add useEffect to get the book that matches the id
useEffect(() => {
// You might do an API call to get the book from the backend here
setBook(bookData.find(b => b.id === id))
}, [])
return (
<CustomScreen>
/////// Modify the elements inside the CustomScreen element
<CustomText title>{book.title}</CustomText>
<CustomText>{book.author}</CustomText>
<Text>{book.summary}</Text>
</CustomScreen>
)
}
export default BookDetails
const styles = StyleSheet.create({})