Nav in Native
Published: 2021-05-11 21:21:46

This week I have been building my first React Native application. I started off with just changing the <View> and styles, making sure I understood how ‘flex’ works and the different core components. To do this I made several component files and took turns returning them as I played with them. But in a real mobile app, which I intended to build, there is navigation, just like in a web app. 

So clearly, this wasn’t going to cut it.
```
return (
    <Welcome />
    // <Index />
  );
```

Note: If you already have an app and want to incorporate React Native, it’s recommending to use the react-native-navigation library [here](https://wix.github.io/react-native-navigation/docs/basic-navigation)

There are many libraries to install to use React Navigation. I’m using expo, so I installed using the following, but you can check out the [documentation](https://reactnavigation.org/docs/getting-started) if you have a different setup for your app. 

```
npm install @react-navigation/native
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
npm install @react-navigation/stack
```

If you are familiar with vanilla React (which you really should be first), then the setup for navigation looks very similar to routes, just different words! The setup should happen at the top level of your app (usually App.js). You start off importing these two libraries:
```
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
```

Inside of your App function, you then need to have a way to call upon the createStackNavigator function, using this line: `const Stack = createStackNavigator();`

That’s the setup! Now you have everything you need to use to wrap up the screens that you want to render. So now my App.js is looking like this:

```
return (
   <NavigationContainer>
     <Stack.Navigator>
       <Stack.Screen name="Welcome" component={Welcome}/>
     </Stack.Navigator>
   </NavigationContainer>
  
 );
```

The next time I had to figure out was using props, so I coud also get my Index component working. For the purposes of testing, I had all my data in the top level of my app (later I plan to replace that with a quick fetch to an API I’ve already picked out). 

For React Native navigation, you can’t pass an inline function like: `component={() => <HomeScreen />}`
Instead, much like you would see for a Route in vanilla React, you wrap the component like so:

```
<Stack.Screen name="Index">
         {props => <Index {...props} cards={cards} />}
</Stack.Screen>
```

In order for my function to properly receive the props, I used memo (there are a few other options, but this worked well for me!)
So I changed this:
```
const Index = (props) => {
   return(
      // render here
   )
}
```
To this: 
```
const Index = React.memo(function Index(props) {
   return(
      // render here
   )
})
```

My Index is using FlatList, so I was getting a warning on my simulator, which I believe is the Native version of the warning you get when you don’t give child components individual keys in vanilla React. So if you get this error: 

Warning: Failed child context type: Invalid child context `virtualizedCell.cellKey` of type `number` supplied to `CellRenderer`, expected `string`.


Add this where you are rendering the components: `keyExtractor={item => item.index_id.toString()}`

Now I successfully had two different components, but only the top one will render when the app starts, and unlike a webpage, you don’t have the option of just putting in the URL to get to a different route. So I added a button to my Welcome screen, to navigate to my Index.

```
<Button color="white"
         onPress={() => {
           navigation.navigate('Index')
         }}
         title="Start"
       />
```

Note: for functional components, it’s a good idea to destructure props, but if you don’t want to do that remember to put `props.navigation.navigate(‘Component’)` instead. 

If you want to navigate one page back you can use an easy back button like so: `<Button title="Go back" onPress={() => navigation.goBack()} />`
Though with native-gesture-handler the user can also swipe to move a page back. 

So that’s the basics of how I set up navigation in my current React Native application! This is definitely the easiest way to get started, and there is so much more to learn further down the line.