Mapas e Rotas com React Native - #8 Organização em Screens
28/02/2021Nesse tutorial trabalharemos com as telas (screens) personalizadas do nosso app construido com React Native, organizando o projeto.
Screens no React Native
Vamos começar instalando o módulo React Navigation e suas dependências:
npm install @react-navigation/native
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-masked-view/masked-view
npm install @react-navigation/stack
expo start --android
Na raiz do nosso projeto vamos criar um diretório views e dentro dela vamos criar os componentes do sistema.
views/Home.js
Receberá o template da página de abertura do nosso app.
import React, {useState,useEffect,useRef} from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import {css} from '../assets/css/Css';
import MapView from 'react-native-maps';
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
import config from '../config';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
import MapViewDirections from 'react-native-maps-directions';
import { MaterialIcons } from '@expo/vector-icons';
export default function Home(props) {
const mapEl=useRef(null);
const [origin,setOrigin]=useState(null);
const [destination,setDestination]=useState(null);
const [distance,setDistance]=useState(null);
const [price,setPrice]=useState(null);
useEffect(()=>{
(async function(){
const { status, permissions } = await Permissions.askAsync(Permissions.LOCATION);
if (status === 'granted') {
let location = await Location.getCurrentPositionAsync({enableHighAccuracy: true});
setOrigin({
latitude: location.coords.latitude,
longitude: location.coords.longitude,
latitudeDelta: 0.000922,
longitudeDelta: 0.000421
})
} else {
throw new Error('Location permission not granted');
}
})();
},[]);
return (
<View style={css.container}>
<MapView
style={css.map}
initialRegion={origin}
showsUserLocation={true}
zoomEnabled={false}
loadingEnabled={true}
ref={mapEl}
>
{destination &&
<MapViewDirections
origin={origin}
destination={destination}
apikey={config.googleApi}
strokeWidth={3}
onReady={result=>{
setDistance(result.distance);
setPrice(result.distance*3);
mapEl.current.fitToCoordinates(
result.coordinates,{
edgePadding:{
top:50,
bottom:50,
left:50,
right:50
}
}
);
}
}
/>
}
</MapView>
<View style={css.search}>
<GooglePlacesAutocomplete
placeholder='Para onde vamos?'
onPress={(data, details = null) => {
setDestination({
latitude: details.geometry.location.lat,
longitude: details.geometry.location.lng,
latitudeDelta: 0.000922,
longitudeDelta: 0.000421
});
}}
query={{
key: config.googleApi,
language: 'pt-br',
}}
enablePoweredByContainer={false}
fetchDetails={true}
styles={{
listView:{backgroundColor:'#fff', zIndex:10},
container:{position:'absolute',width:'100%'}
}}
/>
{distance &&
<View style={css.distance}>
<Text style={css.distance__text}>Distância: {distance.toFixed(2).replace('.',',')}km</Text>
<TouchableOpacity style={css.price} onPress={() => props.navigation.navigate('Checkout',{price: price.toFixed(2)})}>
<Text style={css.price__text}><MaterialIcons name="payment" size={24} color="white" /> Pagar R${price.toFixed(2).replace('.',',')}</Text>
</TouchableOpacity>
</View>
}
</View>
</View>
);
}
App.js
Nosso entry point ficará mais limpo da seguinte maneira:
import React, {useState,useEffect,useRef} from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import {Home, Checkout} from './views';
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} options={{headerShown:false}} />
<Stack.Screen name="Checkout" component={Checkout} options={{headerShown:false}} />
</Stack.Navigator>
</NavigationContainer>
);
}
views/index.js
Vamos criar o arquivo index para fazer as importações automáticas dos componentes do diretório views:
import Home from './Home';
import Checkout from './Checkout';
export {Home, Checkout};
views/Checkout.js
Vamos criar também a screen checkout que ficará responsável por receber os dados de pagamento futuramente:
import React, {useState,useEffect,useRef} from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import {css} from '../assets/css/Css';
export default function Checkout(props) {
return (
<View style={css.container}>
<Text>O valor da corrida é {props.route.params.price}</Text>
</View>
);
}
Por hoje é só turma. Sucesso nos códigos e na vida!
Precisando de assessoria? webdesignemfoco@gmail.com