Guia Completo para Navegação no React Native com TypeScript
Published: 2024-06-23 01:34:08

## Introdução
Neste artigo, vamos explorar como configurar a navegação em um projeto React Native usando TypeScript. Vamos cobrir dois tipos populares de navegadores: o Bottom Tab Navigator e o Stack Navigator. Também abordaremos a estrutura dos tipos de navegação, como definir e usar parâmetros, e a razão de usar undefined em certos casos.

## Pré-requisitos
Antes de começarmos, certifique-se de ter o React Native instalado e configurado em seu ambiente de desenvolvimento. Se você não fez isso, siga a documentação oficial para configurar seu ambiente.

## Passo 1: Configuração do Projeto
**1.1 Criação do Projeto**
Crie um novo projeto React Native:

```
npx react-native init MyNavigationApp
cd MyNavigationApp
```


**1.2 Instalação das Dependências**
Instale as dependências necessárias para o React Navigation:

```
npm install @react-navigation/native @react-navigation/bottom-tabs @react-navigation/stack
npm install react-native-screens react-native-safe-area-context
```

**Instale as definições de tipos para TypeScript:**

```
npm install --save-dev @types/react @types/react-native
npm install --save-dev @types/react-navigation @types/react-navigation-bottom-tabs @types/react-navigation-stack
```

## Passo 2: Definindo Tipos de Navegação
Antes de configurar os navegadores, é essencial definir os tipos de navegação. Isso ajuda a garantir que a navegação seja tipada corretamente, evitando erros comuns.

**2.1 Crie um Arquivo de Tipos**
Crie um arquivo navigationTypes.ts para definir os tipos de parâmetros de navegação:

```
// src/navigationTypes.ts

// Define os parâmetros de navegação para o Bottom Tab Navigator
export type BottomTabNavigatorParams = {
  Home: {
    screen: string;
    params: {
      sort: string;
    };
  };
  Settings: undefined; // Esta tela não espera nenhum parâmetro
};

// Define os parâmetros de navegação para o Stack Navigator
export type StackNavigatorParams = {
  Home: undefined; // Esta tela não espera nenhum parâmetro
  Details: {
    itemId: number;
    otherParam: string;
  };
};
```

**Por Que Usar undefined?**
Quando uma tela não espera nenhum parâmetro, usamos `undefined` para indicar isso. Isso ajuda o TypeScript a garantir que você não passe acidentalmente parâmetros para uma tela que não espera nenhum. Por exemplo:

```
type StackNavigatorParams = {
  Home: undefined; // A tela Home não espera nenhum parâmetro
  Details: {
    itemId: number;
    otherParam: string;
  };
};
```

**Estrutura dos Parâmetros**
No exemplo acima, a tela `Details` espera dois parâmetros: `itemId` e `otherParam`. Isso é definido no tipo `StackNavigatorParams`.

## Passo 3: Configuração do React Navigation
**3.1 Configuração Inicial**
Configure a inicialização do `React Navigation` no arquivo `index.js`:

```
import 'react-native-gesture-handler';
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);

3.2 Configuração do App.tsx com Bottom Tab Navigator

// App.tsx
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import HomeScreen from './src/screens/HomeScreen';
import SettingsScreen from './src/screens/SettingsScreen';

// Importa os tipos definidos no arquivo de tipos
import { BottomTabNavigatorParams } from './src/navigationTypes';

// Criação do Bottom Tab Navigator
const Tab = createBottomTabNavigator<BottomTabNavigatorParams>();

// Componente principal com a navegação
export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}
```

**3.3 Configuração do App.tsx com Stack Navigator**

```
// App.tsx
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './src/screens/HomeScreen';
import DetailsScreen from './src/screens/DetailsScreen';

// Importa os tipos definidos no arquivo de tipos
import { StackNavigatorParams } from './src/navigationTypes';

// Criação do Stack Navigator
const Stack = createStackNavigator<StackNavigatorParams>();

// Componente principal com a navegação
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
```

## Passo 4: Criando as Telas
**4.1 Tela Home para Bottom Tab Navigator**

```
// src/screens/HomeScreen.tsx
import * as React from 'react';
import { View, Text, Button } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
import { BottomTabNavigatorParams } from '../navigationTypes';

type HomeScreenNavigationProp = BottomTabNavigationProp<BottomTabNavigatorParams, 'Home'>;

const HomeScreen: React.FC = () => {
  const navigation = useNavigation<HomeScreenNavigationProp>();

  const navigateToFeed = () => {
    navigation.navigate('Home', {
      screen: 'Feed',
      params: { sort: 'latest' },
    });
  };

  return (
    <View>
      <Text>Home Screen</Text>
      <Button title="Go to Feed" onPress={navigateToFeed} />
    </View>
  );
};

export default HomeScreen;
```
**4.2 Tela Settings para Bottom Tab Navigator**

```
// src/screens/SettingsScreen.tsx
import * as React from 'react';
import { View, Text } from 'react-native';

const SettingsScreen: React.FC = () => {
  return (
    <View>
      <Text>Settings Screen</Text>
    </View>
  );
};

export default SettingsScreen;
```
**4.3 Tela Home para Stack Navigator**

```
// src/screens/HomeScreen.tsx
import * as React from 'react';
import { View, Text, Button } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { StackNavigatorParams } from '../navigationTypes';

type HomeScreenNavigationProp = StackNavigationProp<StackNavigatorParams, 'Home'>;

const HomeScreen: React.FC = () => {
  const navigation = useNavigation<HomeScreenNavigationProp>();

  const navigateToDetails = () => {
    navigation.navigate('Details', {
      itemId: 42,
      otherParam: 'anything you want here',
    });
  };

  return (
    <View>
      <Text>Home Screen</Text>
      <Button title="Go to Details" onPress={navigateToDetails} />
    </View>
  );
};

export default HomeScreen;
```

**4.4 Tela Details para Stack Navigator**

```
// src/screens/DetailsScreen.tsx
import * as React from 'react';
import { View, Text } from 'react-native';
import { useRoute, RouteProp } from '@react-navigation/native';
import { StackNavigatorParams } from '../navigationTypes';

type DetailsScreenRouteProp = RouteProp<StackNavigatorParams, 'Details'>;

const DetailsScreen: React.FC = () => {
  const route = useRoute<DetailsScreenRouteProp>();

  // Acessando parâmetros
  const { itemId, otherParam } = route.params;

  return (
    <View>
      <Text>Details Screen</Text>
      <Text>itemId: {itemId}</Text>
      <Text>otherParam: {otherParam}</Text>
    </View>
  );
};

export default DetailsScreen;
```

## Passo 5: Entendendo e Usando Parâmetros
**Como Definir Parâmetros**
No exemplo acima, a tela `Details` espera dois parâmetros: `itemId` e `otherParam`. Esses parâmetros são definidos no tipo `StackNavigatorParams`.
```
// src/navigationTypes.ts
export type StackNavigatorParams = {
  Home: undefined; // Esta tela não espera nenhum parâmetro
  Details: {
    itemId: number;
    otherParam: string;
  };
};
```

**Como Navegar com Parâmetros**
Para navegar para a tela Details com os parâmetros `itemId` e `otherParam`, usamos o `navigate` como mostrado no exemplo da `HomeScreen`:

```
const navigateToDetails = () => {
  navigation.navigate('Details', {
    itemId: 42,
    otherParam: 'anything you want here',
  });
};
```

**Como Receber Parâmetros**
Para acessar os parâmetros dentro de uma tela, usamos o hook `useRoute` do `React Navigation`:
```
import { useRoute, RouteProp } from '@react-navigation/native';

type DetailsScreenRouteProp = RouteProp<StackNavigatorParams, 'Details'>;

const DetailsScreen: React.FC = () => {
  const route = useRoute<DetailsScreenRouteProp>();

  // Acessando parâmetros
  const { itemId, otherParam } = route.params;

  return (
    <View>
      <Text>Details Screen</Text>
      <Text>itemId: {itemId}</Text>
      <Text>otherParam: {otherParam}</Text>
    </View>
  );
};

export default DetailsScreen;
```

**Conclusão**
Este guia detalhado mostrou como configurar tanto o Bottom Tab Navigator quanto o Stack Navigator com TypeScript em um projeto React Native. Começamos definindo os tipos de navegação para garantir uma tipagem segura ao longo do projeto. Em seguida, configuramos os navegadores e criamos telas simples para demonstração. Discutimos também a estrutura dos tipos de parâmetros de navegação e por que usamos `undefined` para indicar telas que não esperam parâmetros.

Implementar navegação em um aplicativo é um passo fundamental para proporcionar uma experiência de usuário fluida e intuitiva. Com o React Navigation e TypeScript, você pode construir aplicativos robustos e com menos erros de tipagem, melhorando a qualidade e a manutenibilidade do código.

Espero que este guia tenha sido útil e que você agora se sinta confortável para começar a implementar navegação em seus próprios projetos React Native com TypeScript!