Just-in-Time Learning initiative

Version 1.2

Streamlining imports and navigation

React Native versions 50 and later make it easier to navigate among screens, but it can still be tricky to customize the properties for a detail screen based on the context. Try these updates to the script for the tutorial "React Native: Customize a Screen" to make your code simpler.

Unnecessary imports

You still need to import React Native components like StyleSheet and View into every component and screen, but no longer need to import React itself unless you need a hook like useState or useEffect.


// This is no longer necessary.
❌ import React from 'react';
// This could be necessary if you're using a React hook, like a state variable or listener.
🤷‍♂️ import { useState, useEffect } from "react";

If a line in an Expo Snack is grayed out, you aren't currently relying on that variable or feature. If you mean to use it, add the feature somewhere in your code. If you don't, it's probably safe to delete any grayed-out lines.

Importing React Navigation

App.js

This is the only place you need to add these lines:


import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";

Screen components

Technically, if you've imported React Native into App.js, you can access navigation by passing it into any screen component. However, for consistency, I recommend using the useNavigation hook shown below for screen components too.

All components

The navigation property is not automatically passed to non-screen components. To use navigation in an arbitrary component--say, a special button that takes the user from one screen to another--add this line to the import statements at the top of the button component's file:


import { useNavigation } from '@react-navigation/native';

Then add this inside your component's main function, above the return() statement:


const navigation = useNavigation();

Now you can use navigation.navigate to move from one screen to another as usual.


<Button onPress={ () => navigation.navigate("Pets") }>

Of course, if you're navigating to a component (like a detail screen) that depends on custom parameters, you'll need to pass an object containing them as a second argument to navigation.navigate.


<Button onPress={ () => navigation.navigate(
	"Pets", 
	{
		petName,
		petBreed,
		petAge
	}
) }>

The point is that you don't have to worry about the navigation object itself, because the useNavigation() hook returns the navigation prop of whatever screen it's inside. This method is more straightforward than passing the navigation prop as one of the component's parameters and saves the annoyance of passing navigation through multiple, deeply nested child components.

🙂 You only need to apply useNavigation() in a component that explicitly includes the option to move to another screen; you can ignore it for all the other parents and children.

Accessing custom screen properties

Each screen has a special property called route, which conveniently contains any custom details (params) you want to pass to a detail screen.

As long as you are passing navigation via the useNavigation() hook described above, the simplest approach to customizing component properties is only to pass the route:


const PetDetailScreen = ({route}) => {
  navigation = useNavigation();
  const { petName, petImage, petDescription, petLink } = route.params;
  ...
}

🙂 You only need to add the route property to a component that uses custom content. You can leave it out in every other component.

Summary

App.js gets:


import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

Any screen or component that explicitly navigates to a new screen gets:


import { useNavigation } from '@react-navigation/native';
...
const navigation = useNavigation();

Any component that passes custom details to the next screen gets:


import { useNavigation } from '@react-navigation/native';
...
const navigation = useNavigation();
...
onSomething ={
	() => navigation.navigate(
		'MyScreenName',
		{
		  myFirstProperty,
		  mySecondProperty,
		  myThirdProperty,
		}
	)
}

Any detail screen that depends on custom details passed to it from another screen:


const myDetailScreen = ({ route }) => {
	const { myFirstProperty, mySecondProperty, myThirdProperty } = route.params;

Sample code with streamlined imports and navigation

🧁 For an example of a multi-screen app that takes advantage of the useNavigation() and route features to display custom content for the same detail screen, see this Snack.