|
| 1 | +--- |
| 2 | +id: upgrading-from-4.x |
| 3 | +title: Upgrading from 4.x |
| 4 | +sidebar_label: Upgrading from 4.x |
| 5 | +--- |
| 6 | + |
| 7 | +> TODO: This guide is a work in progress. Please send pull requests to improve it. |
| 8 | +
|
| 9 | +React Navigation 5 has a completely new component based API. While the main concepts are the same, the API is different. In this guide, we aim to document all the differences so that it's easier to upgrade your app. |
| 10 | + |
| 11 | +You can also use the [compatibility layer](compatibility.md) to reuse code using the old API with minimal changes. |
| 12 | + |
| 13 | +## Configuring the navigator |
| 14 | + |
| 15 | +In React Navigation 4.x, we used to statically configure our navigator to `createXNavigator` functions. The first parameter was an object containing route configuration, and the second parameter was configuration for the navigator. |
| 16 | + |
| 17 | +```js |
| 18 | +const RootStack = createStackNavigator( |
| 19 | + { |
| 20 | + Home: { |
| 21 | + screen: HomeScreen, |
| 22 | + navigationOptions: { title: 'My app' }, |
| 23 | + }, |
| 24 | + Profile: { |
| 25 | + screen: ProfileScreen, |
| 26 | + params: { user: 'me' }, |
| 27 | + }, |
| 28 | + }, |
| 29 | + { |
| 30 | + initialRouteName: 'Home', |
| 31 | + defaultNavigationOptions: { |
| 32 | + gestureEnabled: false, |
| 33 | + }, |
| 34 | + } |
| 35 | +); |
| 36 | +``` |
| 37 | + |
| 38 | +With 5.x, we now configure the navigator inside a component. First, we create `Navigator` and `Screen` pair using `createXNavigator` and then use them to render our navigator. |
| 39 | + |
| 40 | +There are few key differences here: |
| 41 | + |
| 42 | +- All of the configuration is passed as props to the navigator |
| 43 | +- The route configuration is done using `Screen` elements and passed as children |
| 44 | +- `params` becomes `initialParams` prop on `Screen` |
| 45 | +- `navigationOptions` becomes `options` prop on `Screen` |
| 46 | +- `defaultNavigationOptions` becomes `screenOptions` prop on `Navigator` |
| 47 | + |
| 48 | +```js |
| 49 | +const Stack = createStackNavigator(); |
| 50 | + |
| 51 | +function RootStack() { |
| 52 | + return ( |
| 53 | + <Stack.Navigator |
| 54 | + initialRouteName="Home" |
| 55 | + screenOptions={{ gestureEnabled: false }} |
| 56 | + > |
| 57 | + <Stack.Screen |
| 58 | + name="Home" |
| 59 | + component={HomeScreen} |
| 60 | + options={{ title: 'My app' }} |
| 61 | + /> |
| 62 | + <Stack.Screen |
| 63 | + name="Profile" |
| 64 | + component={ProfileScreen} |
| 65 | + initialParams={{ user: 'me' }} |
| 66 | + /> |
| 67 | + </Stack.Navigator> |
| 68 | + ); |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +## The `navigation` prop |
| 73 | + |
| 74 | +In React Navigation 4.x, the `navigation` prop contained various helper methods as well as the current screen's state. In React Navigation 5.x, we have split the `navigation` prop into 2 props: `navigation` prop contains helper methods such as `navigate`, `goBack` etc., `route` prop contains the current screen's data (previously accessed via `navigation.state`). |
| 75 | + |
| 76 | +This means, now we can access screen's params through `route.params` instead of `navigation.state.params`: |
| 77 | + |
| 78 | +```js |
| 79 | +function ProfileScreen({ route }) { |
| 80 | + const useerId = route.params.me; |
| 81 | + |
| 82 | + // ... |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +Previously we could also use `navigation.getParam('someParam', 'defaultValue')` to get a param value. It addressed 2 things: |
| 87 | + |
| 88 | +- Guard against `params` being `undefined` in some cases |
| 89 | +- Provide a default value if the `params.someParam` was `undefined` or `null` |
| 90 | + |
| 91 | +Now, the same thing can be achieved using the upcoming [optional chaining](https://github.com/tc39/proposal-optional-chaining) and [nullish coalescing](https://github.com/tc39/proposal-nullish-coalescing) operators: |
| 92 | + |
| 93 | +```js |
| 94 | +navigation.getParam('someParam', 'defaultValue'); |
| 95 | +``` |
| 96 | + |
| 97 | +is equivalent to: |
| 98 | + |
| 99 | +```js |
| 100 | +route.params?.someParam ?? 'defaultValue'; |
| 101 | +``` |
| 102 | +
|
| 103 | +Remember to add the Babel plugins for [optional-chaining](https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining) and [nullish-coalescing-operator](https://babeljs.io/docs/en/next/babel-plugin-proposal-nullish-coalescing-operator). |
| 104 | +
|
| 105 | +## Specifying `navigationOptions` for a screen |
| 106 | +
|
| 107 | +In React Navigation 4.x, we could do the following to specify `navigationOption`: |
| 108 | +
|
| 109 | +```js |
| 110 | +class ProfileScreen extends React.Component { |
| 111 | + static navigationOptions = { |
| 112 | + headerShown: false, |
| 113 | + }; |
| 114 | + |
| 115 | + render() { |
| 116 | + // ... |
| 117 | + } |
| 118 | +} |
| 119 | +``` |
| 120 | +
|
| 121 | +With React Navigation 5.x, we need to pass the configuration when defining the screen: |
| 122 | +
|
| 123 | +```js |
| 124 | +<Stack.Screen |
| 125 | + name="Profile" |
| 126 | + component={ProfileScreen} |
| 127 | + options={{ headerShown: false }} |
| 128 | +/> |
| 129 | +``` |
| 130 | +
|
| 131 | +For dynamic options, the `options` prop also accepts a function which receives the `navigation` and `route` props: |
| 132 | +
|
| 133 | +```js |
| 134 | +<Stack.Screen |
| 135 | + name="Profile" |
| 136 | + component={ProfileScreen} |
| 137 | + options={({ route }) => ({ title: route.params.user })} |
| 138 | +/> |
| 139 | +``` |
| 140 | +
|
| 141 | +In addition to this, React Navigation 5.x has another way to configure screen dynamically based on a screen's props or state by calling `navigation.setOptions`: |
| 142 | +
|
| 143 | +```js |
| 144 | +function SelectionScreen({ navigation }) { |
| 145 | + const [selctionCount, setSelectionCount] = React.useState(0); |
| 146 | + |
| 147 | + navigation.setOptions({ |
| 148 | + title: |
| 149 | + selctionCount === 0 ? 'Select items' : `${selectionCount} items selected`, |
| 150 | + }); |
| 151 | + |
| 152 | + // ... |
| 153 | +} |
| 154 | +``` |
0 commit comments