Git Product home page Git Product logo

papareact's Introduction

🔴 Let's build Uber 2.0 with REACT NATIVE! (Navigation, Redux, Tailwind CSS & Google Autocomplete)

Creating Uber 2.0 with React Native: Building a Dynamic and Interactive Ride-Sharing App

In this tutorial, we will be diving into building Uber 2.0 using React Native. This highly anticipated project will cover iOS and Android development, incorporating technologies like Tailwind and Redux. One of the exciting features we will be implementing is Google Places auto-complete, allowing users to easily search for and select their desired destination. Get ready to learn and create an amazing app, and don't forget to share your excitement and where you're watching from. Let's embark on this journey to build an incredible React Native app together!

"
});

import React from "react";
import { View, Text, StyleSheet } from "react-native";

// 1. Set up redux

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Let's build UBER!</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

In this tutorial, we're building Uber 2.0 using React Native, covering both iOS and Android development with technologies like Tailwind and Redux. One key feature is Google Places auto-complete, which allows users to search and select their desired destination easily. The app includes a fully interactive map with navigation from point A to point B, clickable points, and automatic resizing. It utilizes Google Distance Matrix API to calculate distances, travel time, and pricing for different options. The app even allows users to click on each option, providing the actual travel time for the selected route. This powerful and highly anticipated project is sure to excite developers and users alike, with many of you already sharing your excitement and locations, such as Manchester, Basingstoke, and Milton Keynes. Let's continue on this journey to build an incredible React Native app together!

Contenda image

In this tutorial, we continue to build the Uber 2.0 React Native app by adding more functionality, such as interactive navigation and dynamic resizing. One example is swiping back to return to the top and start the whole process again. For instance, you can search for a route from the London Eye to Germany, and the app will provide the cost, distance, and travel time.

The app is fully responsive, allowing you to interact with the map, and it even adjusts when the keyboard is opened, pushing the entire screen up. This level of detail and functionality has generated a lot of excitement among developers, so get ready to dive in and expand your React Native skills as we continue to build this incredible app together.

Contenda image

As we break down the build process for the Uber 2.0 clone, it's important to note that we're using React Native. If you're familiar with React, you'll be well-prepared to tackle this project. So don't worry, and feel confident to take the plunge and expand your React Native skills as we create this incredible app together.

Contenda image

Master React Native and Build Feature-Rich Uber 2.0 and Airbnb Apps with Exciting Challenges and Prizes

In this tutorial, we'll not only cover cool React concepts, but we'll also introduce you to React Native, allowing you to create your own iOS and Android apps. This exciting and fun journey will help you expand your React Native skills and build an amazing app together. So gear up for an engaging and hyped experience!

Contenda image

In this tutorial, we'll be leveraging multiple Google APIs, such as the Directions API, Places API, and Distance Matrix API. These APIs enable us to calculate travel times, distances, and much more. Get ready to explore the full potential of these powerful tools as we continue to develop our feature-rich Uber 2.0 clone using React Native.

Contenda image

In addition to the progress we've made on the Uber 2.0 clone, I've updated the playlist for easy access. Don't forget to sign up for the newsletter below to stay updated on the project. But remember, our journey doesn't stop here. We have a lot more in store as we continue to develop this amazing app using React Native, so stay tuned for more exciting features and enhancements!

Contenda image

In this tutorial, we face a massive challenge as we build both Uber 2.0 and Airbnb using React Native. We'll be using various technologies and libraries, such as Tailwind CSS, Redux, React Native Elements, and React Navigation. You'll learn how to use Tailwind CSS in React Native and work with Redux, a popular requirement for many jobs. We'll also dive into using React Native Elements and React Navigation for smoother screen transitions.

Additionally, we'll be incorporating React Native Maps for iOS and Android, pushing the boundaries and making this build accessible to beginners. We have a lot to look forward to as we explore various hooks, practices, and tools needed to develop these incredible apps. To make things even more exciting, there's a 5-day challenge coming up, starting next Tuesday, where we'll cover Airbnb and teach you how to use Mapbox with normal React.

As a bonus, signing up for the challenge will give you access to a free book valued at £50 and tons of prizes. If you're new to React, don't worry! There's a free Skillshare 101 Basics React class available via the second link in the description. So, grab your water and coffee, and let's jump into building these amazing apps together!

Contenda image

In this tutorial, we face the exciting challenge of building the Uber 2.0 and Airbnb apps using React Native. We'll employ various technologies and libraries, such as Tailwind CSS, Redux, React Native Elements, and React Navigation. You'll learn how to use Tailwind CSS in React Native, work with Redux, and explore React Native Elements and React Navigation for seamless screen transitions.

We'll also incorporate React Native Maps for both iOS and Android, making this build accessible even to beginners. As we proceed, we'll delve into various hooks, practices, and tools necessary for developing these incredible apps. On top of that, a 5-day challenge is coming up, which will cover Airbnb and teach you how to use Mapbox with normal React.

Additionally, signing up for the challenge grants you access to a free book valued at £50 and numerous prizes. If you're new to React, don't worry! A free Skillshare 101 Basics React class is available via the second link in the description. So, grab your water and coffee, and let's dive into building these fantastic apps together!

Contenda image

Setting Up Your React Native Development Environment with Expo

In this tutorial, we'll be using Expo, a highly recommended tool for React Native development. Expo allows you to use your iPhone or Android as a test device, making it an incredibly versatile and powerful tool for developers. As we continue building our app, remember that it's designed to work on both iOS and Android devices. Many of you are enthusiastic and ready to embark on this journey, with shoutouts to Gauraro Gerard, Arjun Joshi, Aldo, Luke, and ShopsRite. Let's jump in and create this fantastic app together!

Contenda image

In this tutorial, we'll begin by setting up the development environment using Expo, a highly recommended tool for React Native development. To start, make sure you have React Native installed and set up on your machine. If you're new to React, you can strengthen your fundamentals in HTML, CSS, and JavaScript before diving into React Native development.

First, install the Expo CLI globally on your machine by running npm install -g expo-cli. This command allows you to use Expo commands in your terminal. After installation, close and reopen your terminal to ensure the changes take effect.

Next, create a new Expo project by running expo init [project-name]. In this case, we'll use expo init UberCloneYT. This command initiates a new Expo project in a directory with the specified name. Feel free to follow along and code with us as we proceed with building the Uber 2.0 clone using React Native.

Contenda image

Now, press the Enter key to initialize the new Expo project. This step will create a new directory with the specified project name and set up the necessary files and folders for your React Native app. As we continue developing the Uber 2.0 clone, you can follow along and code with us to enhance your understanding and skills in React Native.

Contenda image

Setting Up Your Development Environment for Uber 2.0 Clone using Expo and React Native

In this tutorial, we'll continue setting up the development environment for the Uber 2.0 clone using Expo. When you initialize an Expo app, you might need to upgrade your Expo version. Don't worry, upgrading is straightforward with the required command. After initializing the app, you'll be presented with two workflow options: "managed workflow" and "bare workflow." Choose the one that best suits your development needs as you proceed with building the Uber 2.0 clone using React Native.

Contenda image

import React from "react";
import { View, Text } from "react-native";
import { Provider } from "react-redux";

// Set up redux
export default function App() {
  return (
    <Provider>
      <View style>
        <Text>Let's build UBER!</Text>
      </View>
    </Provider>
  );
}

In this tutorial, we'll start with a blank managed workflow in the Expo ecosystem. Expo offers numerous benefits, such as the ability to easily test your app on iOS and Android devices. Before Expo, developing for iOS was challenging without a Mac. We'll soon be introducing TypeScript on the channel, but for now, we'll stick with the blank managed workflow. This choice provides a solid foundation for building the Uber 2.0 clone using React Native.

Contenda image

In the past, developing for iOS was challenging without a Mac, as you needed Xcode. However, Expo has made it much easier to develop and test your app on both iOS and Android devices. With Expo, you can simply scan a QR code with your iPhone, and the app loads up on your device. Another advantage of Expo is that it simplifies the process of installing dependencies. While React Native CLI is an option, we recommend using Expo for React Native development until you need to use React Native CLI features. Trust us, it works and makes the development process more convenient.

Contenda image

In this tutorial, we'll be introducing the Redux toolkit into our application, a popular state management library for React Native. To get started, head over to the Redux toolkit website and click on the "Get Started" button. This will provide you with the instructions on how to install the Redux toolkit into your app. If you're interested in learning more about the Redux toolkit and its benefits, you can explore the documentation available on the website. Remember that understanding state management is an essential skill for any React Native developer, so take this opportunity to familiarize yourself with Redux and enhance your app-building abilities.

Contenda image

Setting Up Redux and Integrating it into the Application

With Redux Toolkit installed, let's set up Redux for our application. Create a new file called store.js to store our global data layer. Inside, import configureStore from the Redux Toolkit and navReducer from our soon-to-be-created navSlice file. The store will be set up with an initial state that includes origin, destination, and travelTimeInformation. All three will initially be set to null.

Create a new folder called slices and inside that folder, create a file called navSlice.js. Import createSlice from Redux Toolkit and define the initial state as an object with origin, destination, and travelTimeInformation properties. Then, create the slice by calling createSlice and passing in an object with name, initialState, and reducers. The reducers will be responsible for updating the state when actions are dispatched. Define three reducers for setOrigin, setDestination, and setTravelTimeInformation.

Next, export the actions so that they can be used in other parts of the application. Also, create selectors for each item in the initial state. Selectors are used to access the current state of the data layer. Finally, export the navSlice.reducer, as it will be connected to the store.

Now, in store.js, import the navSlice.reducer as navReducer. In the App.js file, import the Provider from react-redux and wrap the entire application with the Provider, passing in the store as a prop. With this configuration, Redux is now set up and integrated into the application. As you continue building, you'll be able to dispatch actions to update the state and use selectors to access the current state of the data layer.

Contenda image

With the development environment set up and Redux integrated into our application, you'll find that the app works exactly as intended. It looks great, functions smoothly, and provides an excellent foundation for building the Uber 2.0 clone using React Native. As we continue through this tutorial, you'll gain valuable hands-on experience and deepen your understanding of React Native, ultimately enhancing your app-building skills.

Contenda image

Customizing Search Component and Handling Search Results

Now, modify the search component by setting the minimum length for search queries to 2. This way, it will require at least two characters for the search to return results. For example, queries like "UK" will be valid. Additionally, you might notice that the search component currently displays "powered by Google." If you prefer to remove this text, simply set the enablePoweredByContainer attribute to false. This will hide the "powered by Google" message from the search component.

Contenda image

By setting the enablePoweredByContainer attribute to false, you effectively hide the "powered by Google" message, giving a cleaner and more white-labeled appearance to the search component. You're making great progress, and your energy is amazing! Now, when you interact with the search component, you can see that it fetches information as expected.

Contenda image

When handling the onPress event, you will receive an arrow function that provides two pieces of information: data and details. To ensure you receive the details, you need to set a default value of null and fetch the details using fetchDetails. Details include crucial information such as geometry locations and coordinates, which you will need to store and render on the map later. To store these details, dispatch an action that goes into the data layer, which is Redux in this case. Then, use a selector that you set up earlier to retrieve the information from the data layer (Redux) and utilize it within the component. This approach ensures seamless interaction with the search component and the ability to fetch and display the necessary information.

Contenda image

Integrating Google Places API and Enhancing User Experience in React Native App Development

Now, to demonstrate that the search component fetches relevant information, you can add console.log(data) and console.log(details) within the onPress event handler. Save your changes, and open the console with the shortcut Command + J. Next, search for a location, such as "London Bridge", and click on it. The console will display the data and details retrieved from the Google API, including information about the location, such as "one of the best places in the world" and "a beautiful bridge at River Thames". This confirms that the search component is functioning as expected and fetching the necessary details from the Google API.

Contenda image

With the search component functioning correctly and fetching the necessary details from the Google API, let's examine the data and details we receive. Upon inspecting the logged data, you'll find an abundance of information. For example, the geometry object contains the location with longitude and latitude properties. These coordinates are essential for rendering locations on the map later in the development process. By knowing which data to extract from the API response, you can streamline your efforts and efficiently utilize the information to enhance your app's functionality.

Contenda image

Now that we have the information coming through from the Google Places API, we can proceed with the development of our React Native app. This hands-on learning experience will help you further understand React Native and improve your app-building skills. By successfully integrating the Google Places API, we're making great progress and moving forward with our Uber 2.0 clone.

Contenda image

To improve the user experience, let's add a feature that triggers the search when the return key is pressed. To bring up the keyboard in the emulator, use the shortcut Command + K. Now, when you select an option, such as "London Bridge," the app should set the origin to the location you pressed. This enhancement will make it more convenient for users to interact with the search component and select their desired locations.

Contenda image

To push information into the data layer that we set up earlier, we need to use a dispatch action. To accomplish this, we'll create a variable called dispatch. This variable will be used to dispatch actions that update the state in our Redux store, allowing us to interact with the data layer and manage the information within our application.

Contenda image

To interact with the data layer and manipulate the information within our application, we need to dispatch actions. Think of dispatch as a gun; it shoots the action into the data layer along with the payload containing the information we want to change or manipulate. To create a dispatch variable, use the useDispatch hook from react-redux:

const dispatch = useDispatch();

With the dispatch variable, we can now import and use the setDestination and setOrigin actions from our navSlice:

import { setDestination, setOrigin } from './slices/navSlice';

By doing this, we'll be able to effectively dispatch these actions and update the state in our Redux store. This will help us manage the information within our application and get it working as intended.

Contenda image

To push information into the Redux store, we use the dispatch method, which can be visualized as a gun that shoots the action into the data layer along with the payload containing the information we want to change or manipulate. In this case, the action is setOrigin and the payload is an object. This object will store two things for the origin: the location and some information from the API response, specifically the geometry.location.

To dispatch the setOrigin action with the appropriate payload, use the following code:

dispatch(setOrigin({
  location: details.geometry.location,
  // ... other properties as needed
}));

By doing this, we effectively update the state in our Redux store, allowing us to manage the information within our application and get it working as intended. This hands-on learning experience further deepens your understanding of Redux and React Native, improving your app-building skills.

Contenda image

To store the necessary information from the Google API response in the Redux store, you'll need to access the details.geometry.location object, which contains the latitude and longitude. This will be stored in the Redux store and can be accessed later in a different component, such as the map component. Additionally, you'll want to store a description of the location, which can be useful for displaying on the screen. To do this, use data.description. By storing the geometry location and description, you can efficiently utilize the information to enhance your app's functionality.

Contenda image

Optimizing Search Component and Debugging Issues in React Native App

With the search component functioning correctly and fetching the necessary details from the Google API, let's ensure that the destination is set to null by default. This is particularly important when navigating between screens to avoid retaining any previous destination information. To set the destination as null, you can dispatch the setDestination action with a null value:

dispatch(setDestination(null));

Now, the origin and destination are set correctly. When you navigate between screens, the destination will be cleared, ensuring a clean slate for the user to select a new location. This improvement contributes to a more seamless user experience within your React Native app.

Contenda image

While testing the search component, an error occurred stating that navSetSetOrigin is not a function. This indicates that there might be an issue with the dispatch method or the imported action from the navSlice. Double-check the import statement and ensure that the action is properly defined in the navSlice. By fixing this issue, you can continue with the development and testing of your React Native app, ensuring that the search component fetches the necessary details from the Google API and interacts seamlessly with the Redux data layer.

Contenda image

In order to fix the error stating that navSetSetOrigin is not a function, make sure to double-check the import statement for the setOrigin and setDestination actions and confirm that they're correctly defined in the navSlice. After verifying that the navSlice is properly set up and the actions are being exported, test the search component again by searching for a location like "London Bridge." This will help ensure that the search component is functioning correctly, fetching the necessary details from the Google API, and interacting seamlessly with the Redux data layer.

Contenda image

Sometimes, React Native can behave unexpectedly or seem a bit unusual. In such cases, simply refreshing the application might resolve the issue. As we saw previously, everything was set up correctly, and a refresh was all that was needed. So, if you encounter any odd behavior in your React Native app, consider trying a refresh before diving into more in-depth debugging.

Contenda image

Refreshing and Enhancing Your React Native App with Maps and Tailwind CSS

Sometimes, simply refreshing your app can resolve unexpected issues or unusual behavior. For instance, with the search component correctly set up and integrated with the Redux data layer, simply reloading the app might fix any issues. Now, when you click "Get a ride" and search for a location like "London, UK," the information is properly stored in Redux. So, if you encounter any odd behavior in your React Native app, consider trying a refresh before diving into more in-depth debugging.

Contenda image

Now, let's move on to rendering a map on the "Get a ride" screen. Head over to the map screen, where we've already set up the origin information. This will involve integrating the map component into your React Native app, which is an exciting step in the development process. Remember to like, subscribe, and sign up for the Airbnb challenge if you're eager to continue learning. With the map component set up, your app will be one step closer to functioning like a fully-fledged Uber 2.0 clone.

Contenda image

In the map screen, we'll have two primary sections. The first section will be the actual map, which will take up half of the screen. The other half will be dedicated to displaying details in a separate view. By dividing the screen into two distinct sections, you can effectively present both the map and the relevant information in your React Native app. This layout will allow for a more organized and visually appealing user interface.

Contenda image

We'll create two separate views within our map screen to prepare for displaying the map and additional information. Each view will take up half of the screen using Tailwind CSS. To achieve this, we can use Emmet to quickly generate the views:

<View className="h-1/2"></View>
<View className="h-1/2"></View>

Make sure to import Tailwind CSS in your map screen component. This layout will provide an equal distribution of space to both views, leading to a visually appealing and organized user interface. And that's it! You've successfully set up your screen to display both the map and relevant information for your React Native app.

Contenda image

Creating and Integrating a Map Component in React Native

I hope you had a good week, and I'm glad to hear that you're having a good week too. Now that we've set up the map screen with two separate views, we can test it by clicking on the "Get a ride" button. This should take us to the map screen where we can see the two views we created. Great, now we're on the screen, and everything looks good so far!

Contenda image

To create the map view on the "Get a ride" screen, we won't use a SafeAreaView because we want the map to extend into the "dangerous area" for a more immersive experience. So, let's focus on implementing the map within the first half of the screen that we previously set up.

Contenda image

To create a separate map component, first, create a new file called map.js. In this file, use the React Native Functional Export with StyleSheet to generate a functional component. This approach helps keep the logic separate and organized, which is crucial for more complex projects. Once you've created the map component, you can add your desired content or functionality, such as displaying the map view in your React Native app. This type of component organization makes it easier to maintain and modify your application as needed.

// map.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

const Map = () => {
  return (
    <View>
      <Text>I am a map</Text>
    </View>
  );
};

const styles = StyleSheet.create({});

export default Map;

Now you have successfully created a separate map component to handle the map display and related logic in your React Native application.

Contenda image

Now that the map screen is set up with two separate views, let's render the map component in the first view. To do this, import the Map component and replace the placeholder text with <Map />. After making this change, you should no longer see the "I am a map" text in the top half of the screen.

Next, let's focus on making the map look nice. Since the map extends into the "dangerous area," we'll need to figure out how to adjust its appearance to create a more immersive user experience.

Contenda image

To integrate the map view using React Native Maps, first, install the package by running the following command:

yarn add react-native-maps

Once the package is installed, you can import MapView from react-native-maps:

import MapView from 'react-native-maps';

Now you're ready to use the MapView component to display the map view in your React Native app. Refer to the React Native Maps GitHub repo for more information and examples.

Contenda image

Now that we have set up the map screen with two separate views, it's time to render the map component in the first view. Start by importing the Map component and replacing the placeholder text with <Map />. This change will remove the "I am a map" text from the top half of the screen.

Next, let's make the map look visually appealing. Since the map extends into the "dangerous area," we need to adjust its appearance for an immersive user experience. To integrate the map view using React Native Maps, install the package with:

yarn add react-native-maps

After installation, import MapView from react-native-maps:

import MapView from 'react-native-maps';

You are now ready to use the MapView component to display the map view in your React Native app. For more information and examples, refer to the React Native Maps GitHub repo. Enjoy the progress of your app build and keep up the great work!

Contenda image

To render the map view on the screen, let's use an example from the React Native Maps GitHub repo as a starting point. Copy the example, and we'll modify it to fit our requirements. Replace the entire map component with the MapView component and import both MapView and Marker. The Marker will be used later for adding a pin to the map.

import MapView, { Marker } from 'react-native-maps';

After saving your changes, you might notice that the map is not visible. This is because the MapView component needs some styling. Let's add the necessary styles to make the map view visible on the screen.

Contenda image

Enhancing the Map View and User Experience in Your React Native App

To make the map visible, add a Tailwind style to the MapView component by setting style equal to flex-1. This will ensure that the map uses as much room as it can within its half-container, which means it should take up half the screen. Don't forget to import Tailwind CSS in your map component. After saving your changes and clicking on the "Get a ride" button, you should see the map view displaying San Francisco. It's starting to look great! As you progress, the origin will be pulled through and displayed on the map. Keep up the good work and continue refining your React Native app!

Contenda image

When you click the "Get a ride" button, the goal is to display the origin location on the map. For example, if you enter "London, UK" and click "Get a ride," the map should show London. To achieve this, you will need to pass the origin data to the map component and use it to update the map view accordingly. Keep up the good work and continue refining your React Native app!

Contenda image

Thank you for the kind words and support! It's great to see developers from around the world coming together and learning from each other. Your progress in building your React Native app is impressive, and knowing that this content has been helpful to you is truly rewarding. Keep up the excellent work, and enjoy your journey in the world of programming! Best regards from the entire community.

Contenda image

To enhance the user experience when navigating, it's important to focus on displaying essential information on the map. The default map view may be cluttered with unnecessary details. To address this, you can change the mapType attribute to mutedStandard, which simplifies the map appearance. This change highlights the actual navigation, making it easier for users to follow. Here's how you can modify the map view in your React Native app:

<MapView
  mapType="mutedStandard"
  style={styles.map}
  ...
/>

By using the mutedStandard map type, you provide users with a cleaner and more focused navigation experience. Keep refining your app and enhancing the user experience!

Contenda image

Accessing Origin Data and Customizing Map Display in React Native App

To display the origin location on the map, you'll need to access the data from the global store. Using the useSelector hook from Redux, you can fetch the origin data. First, import useSelector and the selectOrigin selector from your navSlice:

import { useSelector } from 'react-redux';
import { selectOrigin } from './navSlice';

Next, use the useSelector hook to retrieve the origin data:

const origin = useSelector(selectOrigin);

This code will access the global store's state, navigate to the nav property and retrieve the value of origin. Now, you can utilize this data to display the origin location on your map.

Contenda image

Now that you have access to the origin data, you can use it to set the initial region of the map. Since the origin is an object, you can access its latitude and longitude properties directly. Update the MapView component's initialRegion attribute as follows:

initialRegion={{
  latitude: origin.location.latitude,
  longitude: origin.location.longitude,
  ...
}}

After saving your changes, the map should now display the specified origin, such as London. Configuring the latitude and longitude deltas can be challenging when starting off, but with practice, you'll soon master this aspect of map customization. Continue refining your React Native app and enjoy the progress!

Contenda image

With the initial region set, you may wonder about the latitude and longitude deltas. Deltas determine the zoom level on the map. Without delving too much into the technical details, a good starting value for street-level distance is typically used. Don't worry, this is the only time you'll need to modify the delta values – once you've set them, managing the rest of the map customization will be much easier. Keep up the great work as you continue developing your React Native app!

Contenda image

Instead of calculating the delta values manually, which can be a headache, there's a simple trick that can save you time and effort. Don't worry about what a delta is or how it's calculated – the important thing is to focus on building and improving your React Native app.

Contenda image

A convenient solution to avoid calculating delta values manually is available, saving you time and effort. For instance, if you input "Scotland, UK" and click "Get a ride," the map will display Scotland without the need for manual delta calculations. This technique simplifies the process of managing map customization and allows you to focus on building and improving your React Native app.

Contenda image

After successfully displaying the map with the origin location, you can now test it by entering different locations. For example, type in "Los Angeles, California, USA" and click "Get a ride." You should see the map update to show Los Angeles. Feel free to experiment with various locations to ensure that the map updates accordingly. This is a great way to verify that your React Native app is working as intended, displaying the correct locations on the map based on user input. Keep up the excellent work!

Contenda image

Now, let's add a marker to the map at the origin location, like London Bridge. To do this, simply place a Marker component within the MapView component, and set its coordinate attribute to the origin's latitude and longitude. Once you've done this, when you search for a location such as "London Bridge" and click "Get a ride," a marker will appear on the map at that location. This feature provides users with a clear visual indication of their chosen origin. Keep experimenting with different locations and improving your React Native app, and don't forget to thank the supportive community for their encouragement!

Contenda image

To display a marker on the map at the origin location, you need to modify the MapView component so that it is no longer self-contained and can have children. Inside the MapView, you can add a Marker component. However, it's important to only render the marker when the origin is available. Here's how you can achieve this:

<MapView ...>
  {origin && (
    <Marker
      coordinate={{
        latitude: origin.location.lat,
        longitude: origin.location.lng,
      }}
    />
  )}
</MapView>

This code snippet checks if the origin exists before rendering the Marker component with the appropriate latitude and longitude coordinates. Now, when you search for a location and click "Get a ride," a marker will appear on the map at the specified origin.

Contenda image

To display a marker on the map at the origin location, you'll need to utilize the Marker component within the MapView component. When the origin is available, the marker should be rendered on the map.

Make sure to use optional chaining to avoid errors when the origin is undefined:

{origin && (
  <Marker
    coordinate={{
      latitude: origin.location.lat,
      longitude: origin.location.lng,
    }}
  />
)}

This code snippet checks if the origin exists before rendering the Marker component with the appropriate latitude and longitude coordinates. Now, when you search for a location and click "Get a ride," a marker will appear on the map at the specified origin. The pin drop feature provides users with a clear visual indication of their chosen location. Plus, your app will support zooming in and out, which further enhances the user experience. Keep experimenting with different locations and refining your React Native app!

Contenda image

To enhance the marker's appearance and provide more information, you can add a title, description, and identifier to the Marker component. Simply include these properties within the component and set their values as desired:

<Marker
  coordinate={...}
  title="Origin"
  description="London Bridge, London UK"
  identifier="origin"
/>

After saving your changes, clicking on the marker will display the title "Origin," the description "London Bridge, London UK," and an identifier. You can customize these properties to match your preferences. While this example doesn't include a live location feature, you can easily implement it by following the documentation. With these enhancements, your React Native app offers an improved user experience that includes informative markers and a fully functional map.

Contenda image

Enhancing User Experience: Disabling Navigation Options Without Specified Origins

By now, you might want to hide the navigation options if the origin hasn't been entered. For example, you don't want to go to the map screen if the user hasn't specified an origin like "Facebook headquarters." To achieve this, go to your navOptions and make some updates. You'll want to make the navigation option unclickable when the origin details are not filled out. This way, your React Native app ensures that users have provided an origin before allowing them to navigate to the map screen, enhancing the overall user experience.

Contenda image

To disable the navigation option when the origin is not specified, you can use the TouchableOpacity component and set its disabled attribute based on the presence of the origin. First, you need to pull the origin using the useSelector hook:

const origin = useSelector(selectOrigin);

Then, set the disabled attribute of the TouchableOpacity component to true if there is no origin:

<TouchableOpacity disabled={!origin} ...>

To visually indicate that the navigation option is disabled, you can adjust the opacity of the container View using the tailwind utility. Add a JSX tag inside the style attribute and conditionally apply the opacity-20 class if there is no origin:

<View style={tailwind(!origin && 'opacity-20')} ...>

Now, the navigation option will appear less prominent when no origin is provided, enhancing the overall user experience of your React Native app.

Contenda image

After refreshing the app, you can now test the updated navigation options. For instance, when you input "London," the button becomes clickable, allowing you to navigate to the map screen and display London. To further demonstrate its functionality, you can try searching for "One Hacker Way," which brings up the Facebook headquarters in Menlo Park. With these improvements, your React Native app provides a better user experience by ensuring that the navigation option is only clickable once an origin has been entered. Go ahead and test different locations to make sure everything works smoothly. And don't forget, all timestamps for this tutorial will be available in the description. Keep experimenting and refining your app!

Contenda image

Implementing Nested Stack Navigator for Enhanced User Experience

Continuing with the development of your React Native app, it's time to implement the bottom section. Head back to your map screen and start working on the remaining parts. As you progress, remember to make use of the free, complete access to the tutorial video, which will be available in a couple of hours. This resource will prove invaluable when reviewing your work. Keep pushing forward and refining your app to create an excellent user experience.

Contenda image

At this point, you have made significant progress on your map screen, and it seems to be functioning well. Now is an excellent time to review your work and make any necessary adjustments. Remember, as you continue to develop your React Native app, strive to create a great user experience by refining and improving each feature. Keep up the good work!

Contenda image

To build the bottom section on the map screen, you can utilize a nested stack navigator that occupies the remaining half of the screen. This nested stack navigator can have its own set of swipable screens, allowing users to navigate back and forth between these screens seamlessly. As you work on this part of your React Native app, keep in mind the importance of creating an intuitive and user-friendly interface. Implementing a nested stack navigator within the map screen will provide users with an enhanced experience, making it easier for them to interact with your app.

Contenda image

To create a nested stack navigator for the bottom section of the map screen, you'll first need to define a new stack navigator within the map screen component. Declare a constant stack and set it equal to the invocation of createStackNavigator:

const stack = createStackNavigator();

This new stack navigator will function as a lower-level navigator within the map screen, similar to the main one in your app.js. Now, you can place this nested stack navigator inside your map screen component using the stack.Navigator element. This will allow users to seamlessly navigate between swipable screens within the bottom section, enhancing their experience and interaction with your React Native app.

Contenda image

To implement the bottom section on the map screen, you'll create a stack navigator with two screens. The first screen will be the "Navigate Card," which prompts users to enter their desired destination. After entering the destination details, users will proceed to the second screen, the "Ride Options Card." This screen will display various ride options like UberX, UberXL, and UberLuxe for users to choose from. By incorporating this nested stack navigator, you'll provide a seamless and user-friendly interface for your React Native app.

Contenda image

Now, go ahead and create a stack.Screen for the "Navigate Card," which is a component you'll need to add:

<stack.Screen name="NavigateCard" component={NavigateCard} />

At the moment, the NavigateCard component doesn't exist, so you'll need to create it. Once you've implemented it, the nested stack navigator will include the "Navigate Card" as one of its screens, allowing users to interact with it within the bottom section of the map screen in your React Native app.

Contenda image

Create a new file called NavigateCard.js and generate a React Native functional component using the Sashi snippet. Type yo in the component and save the file. Now, head back to the MapScreen component and import the NavigateCard component by adding the following import statement:

import NavigateCard from './NavigateCard';

With this import, you should see "yo" displayed on the screen, indicating that the NavigateCard component has been successfully added to the nested stack navigator within the map screen. This is the first step towards creating a seamless and user-friendly interface for your React Native app.

Contenda image

Now, you'll create another screen for the nested stack navigator on the map screen, called "RideOptionsCard." This screen will allow users to choose their preferred ride type, such as UberX, UberXL, or UberLuxe. First, create a new file named RideOptionsCard.js and generate a React Native functional component using the Sashi snippet. Inside the component, add the message "Pick a ride" to provide some context:

// RideOptionsCard.js
...
return (
  <View>
    <Text>Pick a ride</Text>
  </View>
);
...

Next, head back to the MapScreen component and import the RideOptionsCard component:

import RideOptionsCard from './RideOptionsCard';

Now, add a stack.Screen for the "RideOptionsCard" component to the nested stack navigator:

<stack.Screen name="RideOptionsCard" component={RideOptionsCard} />

With these additions, you should see "Pick a ride" displayed on the screen when navigating to the second screen within the bottom section. This confirms that the RideOptionsCard component has been successfully added to the nested stack navigator on the map screen, further enhancing the user experience of your React Native app.

Contenda image

With your React Native app progressing well, it's essential to keep refining and improving each feature to create an excellent user experience. Keep in mind the importance of an intuitive and user-friendly interface as you work on your app. As you continue with the development, remember to make use of the free, complete access to the tutorial video, which will be available in a couple of hours. This resource will prove invaluable when reviewing your work. And don't forget to subscribe and hit the like button if you're enjoying the content, as it helps support the channel and ensures more frequent updates. Keep pushing forward and refining your app to create a fantastic user experience!

Contenda image

Creating and Styling the "Navigate Card" Component

Now let's focus on building the actual "Navigate Card" component. In the NavigateCard.js file, you'll need to set up a few things for the card to function correctly. This component will prompt users to input their desired destination, so be sure to create an intuitive and user-friendly layout. As you continue working on your React Native app, always strive to refine and improve each feature to provide an excellent user experience for your users.

Contenda image

To ensure that the "Navigate Card" component doesn't overlap with the unsafe area at the bottom of the screen, wrap it inside a SafeAreaView. This will keep the component above the unsafe area and preserve its appearance. To do this, import the SafeAreaView from the React Native library:

import { SafeAreaView } from 'react-native';

Next, replace the View element in the NavigateCard.js component with a SafeAreaView:

return (
  <SafeAreaView>
    ...
  </SafeAreaView>
);

Now, the "Navigate Card" component will be safely positioned above the unsafe area at the bottom of the screen, maintaining a user-friendly layout. Additionally, you may want to change the background color of the "Navigate Card" to a gray color, providing a more visually appealing design for your users. Keep refining and improving your app's features to provide an excellent user experience. And remember, the support and engagement of your audience are what make your development journey possible, so don't forget to show your appreciation for their contributions.

Contenda image

To style the "Navigate Card" component with a white background, you can use the Tailwind CSS library. Add the tailwind style to the SafeAreaView in the NavigateCard.js component as follows:

<SafeAreaView style={tailwind('flex-1 bg-white')}>
  ...
</SafeAreaView>

This will give the "Navigate Card" a white background and ensure that it occupies the entire available space within the SafeAreaView. Using Tailwind CSS provides a convenient and efficient way to style your components, enhancing the overall appearance and user experience of your React Native app.

Contenda image

To style the "Navigate Card" component with a white background, you can use the Tailwind CSS library. Add the tailwind style to the SafeAreaView in the NavigateCard.js component as follows:

<SafeAreaView style={tailwind('bg-white flex-1')}>
 ...
</SafeAreaView>

This will give the "Navigate Card" a white background and ensure that it occupies the entire available space within the SafeAreaView. Using Tailwind CSS provides a convenient and efficient way to style your components, enhancing the overall appearance and user experience of your React Native app.

Now, let's add a "Good morning" message to the "Navigate Card" component. In Uber's app, there is a personalized greeting message, so we'll include one in our app, too. To achieve this, insert a Text element with the desired message, like so:

<SafeAreaView style={tailwind('bg-white flex-1')}>
  <Text>Good morning, Sonny</Text>
  ...
</SafeAreaView>

With these changes, your "Navigate Card" component now has a white background and a friendly greeting message, making it more visually appealing and providing a better user experience.

Contenda image

To personalize the "Navigate Card" component, we will add a greeting message. Although our app doesn't currently have login functionality, you can always upgrade it later to include user-specific greetings. For demonstration purposes, we will use a fixed name in the greeting message.

<SafeAreaView style=>
  <Text>Good morning, Sonny</Text>
...
</SafeAreaView>

To style the greeting message, center the text, add a 5-unit padding on the top and bottom, and set the text size to extra large using the following Tailwind CSS classes: text-center, py-5, and text-xl.

<Text style={tailwind('text-center py-5 text-xl')}>Good morning, Sonny</Text>

Now, the "Navigate Card" component includes a personalized greeting message, enhancing the user experience. If you enjoy following this tutorial and would like to show your support, consider sharing your progress on social media and tagging the author's Instagram handle, as it helps them see who is benefitting from their content. Happy coding!

Contenda image

Enhancing the "Navigate Card" Component: Adding Google Places Autocomplete and Custom Styling

After successfully setting up the "Navigate Card" component with a friendly greeting message and white background, you can now find the code on the public GitHub repository. Feel free to grab the code and use it as a reference for your own React Native app. The next step is to add a View to the component, which will further enhance its appearance and functionality. Keep refining your app's features and continue working towards a seamless and user-friendly interface for your users.

Contenda image

As we continue building the "Navigate Card" component, we'll add another Google Places Autocomplete, similar to the one we previously implemented. This new Autocomplete will be responsible for setting the destination. To begin, let's create a new View and apply the necessary styles:

...
return (
  <SafeAreaView style=>
    <Text style=>Good morning, Sonny</Text>
    <View>
      ...
    </View>
  </SafeAreaView>
);
...

With the new View in place, you can now add the Google Places Autocomplete to allow users to input their desired destination. Keep refining your app's features and working towards an intuitive and user-friendly interface for your users.

Contenda image

To style the new View, add a top border with a gray color, and allow it to shrink when necessary. Add the following styles to the View: border-t, border-gray-200, and flex-shrink.

<View style=>
  ...
</View>

Inside this View, create another View that will contain the Google Places Autocomplete component for setting the destination.

<View style=>
  <View>
    {/* Google Places Autocomplete goes here */}
  </View>
</View>

Now you have a properly styled View that can host the Google Places Autocomplete component, enabling users to input their desired destination. Keep refining your app's features and working towards an intuitive and user-friendly interface for your users.

Contenda image

To prepare for adding the Google Places Autocomplete component, you'll need to import it along with the Google Maps API key from your environment variables. Update your imports in the NavigateCard.js file as follows:

import ...
import {GooglePlacesAutocomplete} from '...';
import {GOOGLE_MAPS_APIKEY} from '@env';

Now, within the inner View you created earlier, render the GooglePlacesAutocomplete component as a self-closing component:

<View style=>
  <View>
    <GooglePlacesAutocomplete
      ...
    />
  </View>
</View>

With the Google Places Autocomplete component in place, users can now input their desired destination. Continue refining your app's features and working towards creating an intuitive and user-friendly interface for your users.

Contenda image

Now, let's configure the Google Places Autocomplete component to resemble Uber's user experience. Set the placeholder attribute to "Where to?" as follows:

<GooglePlacesAutocomplete
  placeholder="Where to?"
  ...
/>

Specify the API key and add a debounce of 400 milliseconds. The debounce ensures that the component doesn't search on every keystroke, but rather waits until the user has stopped typing for 400 milliseconds before initiating a search.

<GooglePlacesAutocomplete
  placeholder="Where to?"
  apiKey={GOOGLE_MAPS_APIKEY}
  debounce={400}
  ...
/>

With these adjustments, the "Navigate Card" component now includes a destination input field that closely resembles Uber's user experience. Keep refining your app's features and work towards creating a seamless and user-friendly interface for your users.

Contenda image

You're welcome! It's great to hear that these tutorials have been helpful in improving your React Native and React JS portfolios. Now, moving forward with the styling, you can combine both Tailwind CSS and custom styles to achieve the desired look for your app. For instance, let's create styles for the input boxes. You can do this by creating a new style object and applying it to the relevant components:

const inputBoxStyles = {
  ...
};

// Then, apply the styles to the input boxes:
<View style={inputBoxStyles}>
  ...
</View>

By combining Tailwind CSS and your own custom styles, you can achieve a unique and visually appealing design for your React Native app. Happy coding!

Contenda image

After successfully configuring the Google Places Autocomplete component, you can further refine its appearance by applying custom styles to its container. You can override certain fields in the container by applying a new style object. For example, set the background color to white, add a padding top of 20 units, and set the flex to zero:

const containerOverride = {
  backgroundColor: 'white',
  paddingTop: 20,
  flex: 0,
};

// Apply the styles to the Google Places Autocomplete container:
<GooglePlacesAutocomplete
  ...
  styles={{
    container: containerOverride,
  }}
/>

Upon saving your changes, you'll notice a subtle visual improvement, as the container now has a white background and appropriate padding. Keep refining your app's features and working towards creating a seamless and user-friendly interface for your users.

Contenda image

Additionally, there are two more fields, textInput and textInputContainer, that you can style to enhance the appearance of the Google Places Autocomplete component. Create custom styles for these fields by changing the background color to a subtle gray, setting the border radius to zero, choosing a font size of 18, and adding some padding around the container. Apply these styles to the Google Places Autocomplete component to achieve a more polished look for your app.

// Create custom styles for textInput and textInputContainer
const textInputStyles = ;
const textInputContainerStyles = ;

// Apply the styles to the Google Places Autocomplete component
<GooglePlacesAutocomplete
 ...
  styles=}
/>

Upon applying these styles, you'll notice an improvement in the appearance of the Google Places Autocomplete component. Keep refining your app's features and working towards creating a seamless and user-friendly interface for your users.

Contenda image

After successfully configuring the Google Places Autocomplete component and refining its appearance with custom styles, you have now learned three different ways to style your components in a React Native app: inline styles, StyleSheet styles, and Tailwind CSS. By combining these various styling methods, you can achieve a unique and visually appealing design for your app. Remember that you can use each of these methods depending on your specific requirements and preferences. Keep refining your app's features and working towards creating a seamless and user-friendly interface for your users. Happy coding!

Contenda image

With the "Navigate Card" component coming along nicely, you can further enhance the Google Places Autocomplete by adjusting its properties. Firstly, enable the fetchDetails attribute to fetch additional details about the selected destination. Additionally, disable the "Powered by Google" container to create a cleaner look for your app:

<GooglePlacesAutocomplete
  ...
  fetchDetails
  suppressDefaultStyles
/>

By applying these changes, you not only enhance the functionality of the component but also create a more polished appearance. Remember that your creativity and flexibility can go a long way in determining how to best utilize the various styling techniques available. Keep refining your app's features and working towards creating a seamless and user-friendly interface for your users.

Contenda image

With the "Navigate Card" component set up, it's time to test it out. As an example, try inputting "London." You may not see any results at first because the query is missing. Recall that the query is where you put in your Google Maps API key and specify the language. So, insert your Google Maps key and try again. Now, when you input "London," you should see results as the component has a valid key for querying the Google APIs. Enjoy experimenting with the Google Places Autocomplete component and continue refining your app's features and user interface.

Contenda image

To enable the search functionality when pressing the return key, configure the Google Places Autocomplete component accordingly. This will improve the user experience, making it more intuitive and convenient for users to search for their desired destination. Remember to continuously test and refine your app's features to ensure a seamless and user-friendly interface. Don't worry if you encounter occasional connection issues while working on your app; just make sure to save your progress frequently and keep pushing forward. Happy coding!

Contenda image

Configuring onPress Event and Navigation for Google Places Autocomplete

Now, let's handle the onPress event for the Google Places Autocomplete component. You should use an arrow function that receives two parameters: data and details. To protect against potential errors, set default values for both parameters to null. Here's the code snippet for the onPress event:

<GooglePlacesAutocomplete
  ...
  onPress={(data, details = null) => {
    // Your code here
  }}
/>

This setup allows you to handle user interactions with the autocomplete component and take action based on the selected destination. Make sure to keep testing your app and refining its features to ensure a seamless and user-friendly interface.

Contenda image

With the onPress event configured for the Google Places Autocomplete component, it's time to set the destination. You previously set the origin using dispatch; now, use the same method to set the destination. Here's the updated code snippet:

<GooglePlacesAutocomplete
 ...
  onPress=}
/>

By following this approach, you can now properly set both the origin and destination. Make sure to keep testing your app and refining its features to ensure a seamless and user-friendly interface.

Contenda image

To set the destination, you first need to access the dispatch object using the useDispatch hook from React Redux:

const dispatch = useDispatch();

Next, import the setDestination action from your navigation slice:

import { setDestination } from '...';

With the dispatch object and setDestination action, you can now update the onPress event in the Google Places Autocomplete component to set the destination:

<GooglePlacesAutocomplete
...
  onPress=}
/>

This allows you to properly set both the origin and destination. Continue testing your app and refining its features to ensure a seamless and user-friendly interface.

Contenda image

Now, to set the destination, dispatch the setDestination action with a payload containing the location and description. This approach allows you to handle both the origin and destination effectively. Keep refining your app's features and working towards creating a seamless and user-friendly interface for your users. Your dedication and attention to detail throughout this process are truly commendable. Keep up the great work!

Contenda image

After setting the destination, you'll want to navigate to the next screen. To do this, first obtain the navigation object by using the useNavigation hook:

const navigation = useNavigation();

Make sure to import useNavigation from your navigation library. Now, when a user selects an address from the list, you want to navigate them to the "Pick a Ride" screen. To achieve this, add the navigation action within the onPress event of the Google Places Autocomplete component:

<GooglePlacesAutocomplete
  ...
  onPress={(data, details = null) => {
    // Set destination and other logic
    navigation.navigate("Pick a Ride");
  }}
/>

With this in place, the user will be navigated to the "Pick a Ride" screen upon selecting an address, creating an intuitive and seamless experience. Keep refining your app's features to ensure a user-friendly interface.

Contenda image

Now, to navigate to the "Ride Options Card" screen, use the navigation.navigate method. Make sure you have the navigation object by using the useNavigation hook. Update the onPress event of the Google Places Autocomplete component accordingly:

<GooglePlacesAutocomplete
 ...
  onPress=}
/>

With this setup, when a user selects an address, they will be navigated to the "Ride Options Card" screen, providing an intuitive and seamless experience. If you encounter any issues, double-check your code and ensure the dispatch and navigation objects are set up correctly. Continue refining your app's features to ensure a user-friendly interface.

Contenda image

After refreshing the app, you might encounter a request timeout error. Don't worry, just refresh again and try searching for a location like "London" or "Scotland, UK." Once you see the search results, this means the destination has been successfully pushed into the Redux store, and the app navigates to the next screen. If you want to go back, simply swipe back to return to the previous screen. Keep experimenting with your app and refining its features to ensure a seamless and user-friendly experience for your users.

Contenda image

Enhancing Your Map Component: Integrating Directions and Improving Functionality

With the destination functionality in place, your app has gained significant power and versatility. Now that you have a destination, it's time to enhance your map component. Head back to the map component to make further improvements, ensuring that your app continues to progress and provide a seamless and user-friendly experience for your users. Keep up the great work, and remember that each refinement brings you closer to a polished and effective final product.

Contenda image

As you return to the map component, it's time to introduce the directions API to your app. By incorporating directions, you will greatly enhance your app's functionality. To achieve this, you'll need to include a React Native dependency. The directions implementation is quite slick, and integrating it into your app will contribute to a more seamless and user-friendly experience for your users.

Contenda image

To integrate directions into your map component, you'll need to install the react-native-maps-directions dependency. This will sit inside your MapView component, just like a marker, and provides directions from point A to B. To install the dependency, run the following command:

yarn add react-native-maps-directions

With this dependency installed, you'll be able to greatly enhance your app's functionality by incorporating directions, contributing to a more seamless and user-friendly experience for your users.

Contenda image

Now you can retrieve the destination from the Redux store, just like you did with the origin. To do this, use the useSelector hook to access the selectDestination selector. Don't forget to import it:

const destination = useSelector(selectDestination);

With the destination successfully retrieved, your app now has both the origin and destination information, allowing you to further enhance the map component and provide a seamless and user-friendly experience for your users.

Contenda image

With both the origin and destination retrieved, you can proceed to render the directions on your map. To do this, check if both origin and destination exist, and then render the MapViewDirections component. First, import the component at the top of your file:

import MapViewDirections from 'react-native-maps-directions';

Next, add the MapViewDirections component within your map, providing it with the origin and destination descriptions:

{
  origin &&
  destination &&
  (
    <MapViewDirections
      origin={origin.description}
      destination={destination.description}
      ...
    />
  )
}

This self-closing component takes a variety of attributes to work properly. With this setup, your app will display directions between the origin and destination points, enhancing the user experience and providing a more seamless interface.

Contenda image

Enhancing the Map Component with Directions and Zoom Functionality

With both the origin and destination in hand, you can now render directions on your map using the MapViewDirections component. First, set the destination equal to destination.description, which is the text saved in the store. Then, pass the Google Maps API key from your environment variables:

      destination=destination.description
      apiKey={process.env.GOOGLE_MAPS_API_KEY}
      ...

Next, configure the appearance of the directions by setting the strokeWidth and strokeColor. In this case, we'll use a black line, similar to Uber's design:

      strokeWidth={3}
      strokeColor="black"

After saving your changes, you'll see that the directions are displayed on the map, providing a more seamless and user-friendly experience.

Contenda image

Now that you've successfully integrated the MapViewDirections component and configured its appearance, you can test the directions feature in your app. For example, try setting the origin to Scotland and the destination to London Bridge. You'll see that the app displays a detailed route between the two locations, including roundabouts and streets along the way. This addition of directions greatly enhances your app's functionality, providing a more seamless and user-friendly experience for your users. Keep refining the app and experimenting with different destinations to ensure the directions feature works smoothly.

Contenda image

To solve the problem of zooming out the map when you have both the origin and destination points, we'll implement a smooth method that ensures both points A and B are within the map view. This will provide your users with a more seamless and user-friendly experience when the destination is set.

Contenda image

To reference and manipulate the map, you'll need to use the useRef hook, which acts as a pointer to a specific object or component. Start by creating a map reference using useRef and initialize it with a value of null:

const mapRef = useRef(null);

Next, attach this reference to the MapView component. This way, you can access and modify the map whenever necessary:

<MapView
  ref={mapRef}
  ...
/>

Now, you'll need to utilize the useEffect hook to perform actions when specific conditions are met. The useEffect hook is a core concept in React that allows you to perform side effects in function components.

useEffect(() => {
  ...
}, []);

Pay close attention to the implementation of the useEffect hook, as it will help you create a smooth method for adjusting the map view to ensure both origin and destination points are visible, providing a seamless user experience.

Contenda image

With the destination functionality in place, let's improve the map component by introducing the Directions API. Start by installing the react-native-maps-directions dependency:

yarn add react-native-maps-directions

Retrieve the destination from the Redux store using the useSelector hook and the selectDestination selector:

const destination = useSelector(selectDestination);

Import the MapViewDirections component and render it within your map, providing the origin and destination descriptions:

import MapViewDirections from'react-native-maps-directions';

// Inside your map component
<MapViewDirections
  origin=origin.description
  destination=destination.description
  apiKey=...
  strokeWidth=...
  strokeColor="black"
/>

To ensure that both origin and destination points are visible on the map, use the useRef hook to create a map reference and attach it to the MapView component:

const mapRef = useRef(null);

// Inside your JSX
<MapView
  ref=...
  ...
/>

Next, utilize the useEffect hook to perform actions when the origin or destination changes:

useEffect(() => {
  if (!origin || !destination) return;

  // Add logic here to modify the map view

}, [origin, destination]);

With these enhancements, your app will display directions between the origin and destination points, providing a more seamless and user-friendly experience. Test the directions feature with different destinations to ensure it works smoothly.

Contenda image

To zoom and fit the map view to both the origin and destination markers, you can use the fitToSuppliedMarkers function from the MapView component. First, access the current map reference by calling mapRef.current. Then, use the fitToSuppliedMarkers method and pass an array containing the identifiers of the origin and destination markers as its first argument:

mapRef.current.fitToSuppliedMarkers(['origin', 'destination']);

The origin and destination marker identifiers are the same as the ones you used when creating the markers on the map. By calling this method, the map will automatically adjust its view to ensure both markers are visible, providing a more seamless and user-friendly experience.

Contenda image

Additionally, you can now add the destination marker to the map, similar to how you added the origin marker. Copy the origin marker block and adjust it to use the destination and update the identifier to 'destination'. Remember to import the useEffect hook from React at the top of your file:

import { useEffect } from 'react';

With the markers in place, you can now use the fitToSuppliedMarkers function from the MapView component to zoom and fit the map view to both the origin and destination markers. Access the current map reference by calling mapRef.current and pass an array containing the identifiers of the origin and destination markers as its first argument:

mapRef.current.fitToSuppliedMarkers(['origin', 'destination']);

This method will automatically adjust the map view to ensure both markers are visible, providing a more seamless and user-friendly experience.

Contenda image

You can improve the map view by adding edge padding to provide some space around the markers when the map zooms in. To do this, pass an edgePadding object to the fitToSuppliedMarkers method. This object should have properties for top, left, bottom, and right, all set to a value of 50. This means the map won't zoom in too close to the markers, keeping some padding around them.

mapRef.current.fitToSuppliedMarkers(['origin', 'destination'], {
  edgePadding: { top: 50, left: 50, bottom: 50, right: 50 },
});

Now, when you set the origin and destination – for example, London and Essex – the map will display the route with appropriate padding around the markers. The useEffect hook ensures that the map view will update whenever the origin or destination changes, providing a smooth and user-friendly experience.

Contenda image

Enhancing Map View and User Interface for a Seamless Experience

With the map view improvements in place, try setting the origin to Birmingham, UK, and you'll see the map automatically adjusts to display both origin and destination markers, along with the directions. The fitToSuppliedMarkers function simplifies the process, eliminating the need to deal with deltas and other complexities. This enhancement significantly improves the user experience, making the app more seamless and user-friendly. Keep experimenting with different origin and destination points to ensure the map view adjusts correctly and provides a smooth experience for your users.

Contenda image

Continuing on, the map view is looking good and the directions feature is functioning nicely. For instance, if you set the origin to London Eye or London Bridge, the map smoothly navigates to those locations. Similarly, if you try setting the origin to Scotland, UK, the map zooms out gracefully, providing a slick animation. This demonstrates that the enhancements made to the map view are working effectively, offering users a seamless and enjoyable experience. Keep experimenting with different origin and destination points to ensure the map view continues to adapt and provide a smooth experience for your users.

Contenda image

Now, let's enhance the user interface by adding two buttons at the bottom of the screen, similar to the ones you'd find in the Uber app. These buttons will allow users to pick a ride and proceed with the booking process. To create these buttons, you can add UI components to your existing screen layout. With these buttons in place, your app's appearance will more closely resemble the look and feel of the Uber app, providing a familiar and user-friendly experience to your users.

Contenda image

Adding UI Components and Creating a NavFavorites Component for a User-Friendly Experience

In your home screen component, you can now add two additional UI components at the bottom of the screen, similar to the ones found in the Uber app. These buttons will enable users to choose a ride and proceed with the booking process. Although they won't have any actual functionality at this stage, you can certainly enhance them further to include more functionality as needed. By adding these buttons, your app's appearance will more closely resemble the look and feel of the Uber app, providing a familiar and user-friendly experience for your users.

Contenda image

To create a "NavFavorites" component that resembles the "Go Home" or "Go Here" options typically found in navigation apps, simply define a new functional component in your app. This component will display the favorite destinations, allowing users to easily access their preferred locations.

Contenda image

To create the NavFavorites component, start by making a new file called navFavorites.js in your components folder. Then, create a functional component and export it with a StyleSheet:

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const NavFavorites = () => {
  return (
    <View>
      <Text>This is where the favorites live.</Text>
    </View>
  );
};

const styles = StyleSheet.create({});

export default NavFavorites;

This component will display the favorite destinations, allowing users to easily access their preferred locations. To implement this, you'll want to use a FlatList component for displaying the favorite destinations in a scrollable list.

Contenda image

With the data prepared, you can now display it on the screen. The data can be placed outside the component to avoid clutter. The data will consist of three items: Home, Location, and Destination. These items can be coded to set the destination when clicked, if desired. The data structure will look like this:

const data = [
  {
    id: 1,
    title: 'Home',
    description: 'Home location'
  },
  {
    id: 2,
    title: 'Location',
    description: 'Specific location'
  },
  {
    id: 3,
    title: 'Destination',
    description: 'Destination of choice'
  }
];

With this data in place, you can use the FlatList component to display the favorite destinations in a scrollable list, allowing users to easily access their preferred locations.

Contenda image

Enhancing User Interface with Custom Buttons and NavFavorites Component

Now, let's enhance the user interface by adding two buttons at the bottom of the screen, similar to the ones you'd find in the Uber app. These buttons will allow users to pick a ride and proceed with the booking process. To create these buttons, add UI components to your existing screen layout, making your app's appearance resemble the look and feel of the Uber app, providing a familiar and user-friendly experience.

To create a "NavFavorites" component that resembles the "Go Home" or "Go Here" options typically found in navigation apps, define a new functional component in your app. This component will display favorite destinations, allowing users to easily access their preferred locations. Start by creating a new file called navFavorites.js in your components folder, then create a functional component and export it with a StyleSheet:

import React from 'react';
import { StyleSheet } from 'react-native';

const NavFavorites = () => { ... };

const styles = StyleSheet.create({ ... });

export default NavFavorites;

To implement this component, use a FlatList component for displaying the favorite destinations in a scrollable list. Prepare the data consisting of three items: Home, Location, and Destination, and place it outside the component:

const data = [
  { ... },
  { ... },
  { ... },
];

With this data in place, you can use the FlatList component to display the favorite destinations in a scrollable list, allowing users to easily access their preferred locations. Feel free to experiment with different origin and destination points to ensure the map view continues to adapt and provide a smooth experience for your users.

Contenda image

Celebrating Progress and Implementing the FlatList Component

Now that you've made significant progress, take a moment to appreciate the quality of your work. Your dedication is evident, and the community's response of 1.7k likes is a testament to your hard work. With this momentum, you can continue to create amazing content for React Native. The future looks promising, and there's no doubt that you'll keep delivering exceptional value. Stay motivated and keep pushing the boundaries of what's possible in React Native development.

Contenda image

Now, let's implement the FlatList component within the NavFavorites component. First, import the FlatList at the top of your navFavorites.js file. Then, add the FlatList as a self-closed component within the NavFavorites component. It will require three properties: data, keyExtractor, and renderItem.

For the data property, pass in the data array created earlier. For the keyExtractor, pass in an arrow function that takes the item as an argument and returns the item.id. This will ensure that each item has a unique key during the loop. Finally, for the renderItem, pass in an arrow function that takes the item as an argument and returns a TouchableOpacity component for each item.

import React from 'react';
import { StyleSheet, FlatList, TouchableOpacity } from 'react-native';

const NavFavorites = () => (
  <FlatList
    data={data}
    keyExtractor={(item) => item.id}
    renderItem={({ item }) => (
      <TouchableOpacity>
        ...
      </TouchableOpacity>
    )}
  />
);

const styles = StyleSheet.create();

export default NavFavorites;

The TouchableOpacity component will render as a touchable button for each favorite destination, allowing users to easily access their preferred locations. Don't forget to experiment with different origin and destination points to ensure the map view continues to adapt and provide a smooth experience for your users.

Contenda image

Enhancing the NavFavorites Component with Touchable Buttons and Icons

To create touchable buttons for the favorite destinations, add a TouchableOpacity component inside the FlatList's renderItem function. For now, simply add a text component with the text "test" as a child of the TouchableOpacity:

import React from 'react';
import { ... } from 'react-native';

const NavFavorites = () => (
  <FlatList
    data={data}
    keyExtractor={(item) => item.id}
    renderItem={({ item }) => (
      <TouchableOpacity>
        <Text>Test</Text>
      </TouchableOpacity>
    )}
  />
);

const styles = StyleSheet.create();

export default NavFavorites;

Now, import the NavFavorites component into your home screen component. After doing so, you should see the "test" text displayed twice, corresponding to the two touchable buttons:

// In your home screen component
import NavFavorites from './components/navFavorites';

You can use these touchable buttons in multiple locations within your app, such as on the home screen and another screen. Additionally, consider adding a menu button that navigates back to the main menu, allowing users to return without swiping back.

Contenda image

Now that you have created the NavFavorites component and implemented the FlatList with touchable buttons, it's time to appreciate the progress you have made. You are moving at a great pace and delivering exceptional value with this React Native project. The future looks promising as you continue to push the boundaries of what's possible in React Native development. Keep up the incredible work and remember that you are truly making a difference in the development community.

Contenda image

Continuing with the NavFavorites component, you'll want to add some icons within the TouchableOpacity component to enhance the visual appearance. This will make the favorite destinations more interactive and visually appealing for users.

Contenda image

To improve the visual appearance of the NavFavorites component, you can add icons to each of the items. For this purpose, you can use the icon set from React Native Elements. By rendering an icon with specific styles, you can create a more interactive and visually appealing interface for users to access their favorite destinations. In the next steps, you'll learn how to apply these styles and incorporate icons into your component.

Contenda image

In order to display the icons for each favorite destination, you'll need to render the icons within the TouchableOpacity component. Utilize Tailwind CSS to style the icons with marginRight: 4, borderRadius: 4, backgroundColor: 'gray-300', and padding: 3. To access the icon property from the data array, you can use ES6 destructuring within the FlatList's renderItem function. This allows you to directly access the location, destination, and icon properties from each item in the data array. Now, when you run your app, you should see the icons displayed for each favorite destination, enhancing the visual appearance and interactivity of the NavFavorites component.

Contenda image

With the NavFavorites component created and the FlatList implemented, you've made significant progress in enhancing the user interface of your app. Although the functionality is in place, it's important to keep the visual appearance and interactivity in mind. One way to improve this aspect is by incorporating icons into each favorite destination item.

To add icons to each item, you can use the icon set from React Native Elements. By applying specific styles to these icons, you'll create a more visually appealing and interactive experience for users accessing their favorite destinations. In order to display the icons within the TouchableOpacity component, you'll need to style them using Tailwind CSS, with properties like marginRight: 4, borderRadius: 4, backgroundColor: 'gray-300', and padding: 3.

Additionally, you can use ES6 destructuring within the FlatList's renderItem function to access the location, destination, and icon properties from each item in the data array. With these modifications, your app will display icons for each favorite destination, enhancing both the visual appearance and interactivity of the NavFavorites component.

As you continue to develop your React Native project, remember to stay motivated and inspired by the positive feedback from the community. Keep pushing the boundaries of what's possible in React Native development, and you'll continue to deliver exceptional value.

Contenda image

You've made great progress so far, and now it's time to clean up the appearance of your favorite destinations. Currently, the items in the NavFavorites component are displayed as two large blocks, which isn't very visually appealing. Recall that, by default, items are displayed in columns.

To improve the appearance, you'll need to adjust the styling of the TouchableOpacity component and its children. Keep experimenting with different styles and layouts until you achieve a more visually pleasing result. As you continue to develop your React Native project, never forget the importance of a clean and user-friendly design, as this will greatly impact the overall user experience.

Contenda image

Enhancing Favorite Destinations Appearance in NavFavorites

To refine the appearance of the favorite destinations in the NavFavorites component, you can adjust the styling of the TouchableOpacity component and its children. Start by setting the style of the TouchableOpacity component to tailwind('flex-row items-center p-5'). This makes the items display in a row, centers them, and applies padding.

Next, create a View component with two Text components inside it. Set the first Text component to display the location, and the second one to display the destination. With these changes, your favorite destinations should now appear more organized and visually appealing, providing users with a better overall experience.

Here's how your updated TouchableOpacity component should look:

<TouchableOpacity style={tailwind('flex-row items-center p-5')}>
  <View>
    <Text>{location}</Text>
    <Text>{destination}</Text>
  </View>
</TouchableOpacity>

As you progress with your React Native project, always remember the importance of clean and user-friendly design, as it significantly impacts the user experience.

Contenda image

To finalize the styling for the favorite destinations, you can apply additional styles to the location and destination text components. For the location, set the style to tailwind('font-semibold text-lg'), which will make the text larger and semi-bold. For the destination, set the style to tailwind('text-gray-500'), which will give the text a gray color. With these styling adjustments, your favorite destinations should now look polished and visually appealing.

Here's how your updated Text components should look:

<View>
  <Text style={tailwind('font-semibold text-lg')}>{location}</Text>
  <Text style={tailwind('text-gray-500')}>{destination}</Text>
</View>

Remember, a well-designed user interface is crucial for providing a positive user experience in your React Native project.

Contenda image

Enhancing App Appearance with Customized Item Separators and NavFavorites Integration

Tailwind CSS offers a versatile color palette that can significantly enhance your app's appearance. After styling your favorite destinations, you might want to add separators between items in the FlatList. To do this, you can use the ItemSeparatorComponent prop, which accepts an arrow function that returns JSX.

In this case, you'll create a self-closing View component with a style that uses Tailwind CSS classes. For example, you can set the background color using bg-gray-200. However, when it comes to the height, Tailwind CSS might not provide the granularity you need. If you set the height to 1 using Tailwind CSS, the separator line may appear too thick, and you cannot go lower than that.

Here's an example of how to add an ItemSeparatorComponent with a custom style:

<ItemSeparatorComponent={() => (
  <View style={...}></View>
)} />

Keep in mind that you may need to adjust the separator's style to achieve the desired appearance for your app.

Contenda image

To create a thinner separator line between the items in the FlatList, you can combine Tailwind CSS styles with inline styles. Use an array syntax for the style prop and set the height to 0.5. This will give you a super thin line that serves as a divider between the components. Here's an example of how to mix Tailwind CSS and inline styles in the ItemSeparatorComponent:

<ItemSeparatorComponent={() => (
  <View style={[tailwind('bg-gray-200'), {height: 0.5}]} />
)} />

With this thin separator line, your favorite destinations list will look even more polished and visually appealing. As you continue developing your app, ensure that elements like these enhance the user experience and maintain a clean and user-friendly design.

Contenda image

In the MapScreen component, locate the NavigateCard component. To include the NavFavorites component, simply add it right below the View component within the NavigateCard. This will ensure that your favorite destinations are displayed within the navigation card.

Here's an example of how you should add the NavFavorites component inside the NavigateCard:

<NavigateCard>
  <View>
    ...
  </View>
  <NavFavorites />
</NavigateCard>

With this addition, you should see the favorite destinations appear in the navigation card, providing a more complete and visually appealing interface for users to access their favorite destinations.

Contenda image

Enhancing User Experience with Reusable Components and Keyboard Avoidance

Incorporating reusable components is one of the key strengths of React, as it allows you to significantly improve your app's appearance and functionality. By utilizing these components, you can create a more cohesive and visually pleasing interface while maintaining consistent design patterns throughout your application. In this case, you've successfully integrated the NavFavorites component, upgrading the overall look and feel of your app. Remember that reusable components save time and effort, and they contribute to a more maintainable codebase. Keep embracing the power of React components to continue delivering exceptional value to users.

Contenda image

As a challenge, try expanding the functionality of your app by allowing users to quickly navigate to their favorite destinations with a single tap. Since you've already learned how to handle onPress events and set destinations, you should be able to implement this feature. By adding this shortcut, you'll enhance the user experience, making your app even more convenient and efficient. You've come a long way in building your app, and with your new skills, you can continue to create outstanding features. Keep up the great work!

Contenda image

At this stage, you may have noticed an issue with the layout when the keyboard is activated. When you open the keyboard, it overlaps the bottom part of the screen, making it difficult to interact with the interface, especially on smaller devices. This is not a good user experience. To address this problem, you can use the KeyboardAvoidingView component provided by React Native.

KeyboardAvoidingView is a wrapper component that automatically adjusts the layout when the keyboard is opened, ensuring that the content remains visible and accessible. By wrapping your existing components with KeyboardAvoidingView, you can create a more user-friendly interface that adapts to the presence of the on-screen keyboard.

Contenda image

To address the issue with the layout overlapping the keyboard, you will need to use the KeyboardAvoidingView component from React Native. This component will automatically adjust the layout when the keyboard is opened, ensuring that the content doesn't get covered. First, import the KeyboardAvoidingView from React Native:

import { KeyboardAvoidingView } from 'react-native';

Then, wrap your existing components with the KeyboardAvoidingView to create a more user-friendly interface that adapts to the presence of the on-screen keyboard.

Contenda image

To fix the overlapping keyboard issue, you can utilize the KeyboardAvoidingView component. First, remove the unnecessary StyleSheet imports, since you won't be needing them. Next, import the KeyboardAvoidingView from React Native:

import { KeyboardAvoidingView } from 'react-native';

Position the KeyboardAvoidingView component above the Navigator level, but below the SafeAreaProvider for the icons. Then, wrap all the Navigator contents inside the KeyboardAvoidingView component.

To make the content of the KeyboardAvoidingView visible, you need to give it a flex of 1. There are two methods to achieve this: using Tailwind CSS or inline styling. In this example, we're going to use inline styling:

<KeyboardAvoidingView style={{ flex: 1 }}>
  {/* Navigator contents */}
</KeyboardAvoidingView>

With the KeyboardAvoidingView component in place and styled, your app should now adapt to the presence of the on-screen keyboard, providing a better user experience.

Contenda image

Adjusting KeyboardAvoidingView for Cross-Platform Compatibility

To ensure the KeyboardAvoidingView component works correctly on both iOS and Android platforms, you need to add a behavior attribute. Since the behavior differs between platforms, you can use the Platform provided by React Native to handle the differences. First, import Platform from React Native:

import { Platform } from 'react-native';

Then, set the behavior attribute of the KeyboardAvoidingView component based on the platform. For iOS, use padding, while for Android, use height:

<KeyboardAvoidingView
  style={{ flex: 1 }}
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
  
</KeyboardAvoidingView>

With this configuration, the KeyboardAvoidingView component will adjust the layout properly on both iOS and Android devices when the keyboard is opened, improving the user experience across different platforms.

Contenda image

Now that the layout moves up when the keyboard is activated, you can comfortably type and see all the search results. To further enhance the experience, you can add a keyboardVerticalOffset attribute to the KeyboardAvoidingView component. The value for this attribute is platform-specific. For iOS, use -64 to crop the bottom component by 64 units, while for Android, use 0 since it's handled automatically. This adjustment ensures the keyboard doesn't overlap with any bottom UI elements:

<KeyboardAvoidingView
  style=}
  behavior=}
  keyboardVerticalOffset=>
  
</KeyboardAvoidingView>

With these changes, your app's user experience becomes even better as it now handles the keyboard interaction seamlessly on both iOS and Android devices. Keep refining your app's design and functionality to deliver outstanding value to your users.

Contenda image

Continuing with the development, we are about to implement the distance matrix for the Google API. This feature will enhance the functionality of your app, allowing users to access essential information like distance and travel time between destinations. As you keep adding new features, your app becomes more powerful and valuable to users, so keep up the great work and continue refining your app's design and functionality.

Contenda image

Maximize Your Learning Experience: Enhance Your Skills with React Basics 101 and Upgrade Your App's Functionality

It's fantastic to hear that you've registered online and are excited for the lessons being provided by instructors like Pablo and Ibrahim. As you progress through the course, you'll complete the navigator section and move on to more advanced features like time traveling. Don't forget to take advantage of additional resources like Skillshare's React Basics 101 course. Even if you're already familiar with React, it's always beneficial to revisit the fundamentals and solidify your understanding. Many learners recommend binge-watching these valuable resources to quickly enhance their skills. Keep up the enthusiasm and dedication as you continue to learn and grow in your development journey!

Contenda image

To further improve your React skills, take advantage of the free month of Skillshare that comes with the React Basics 101 course. This resource will help solidify your understanding of React fundamentals and prove beneficial in your development journey. Many learners find it helpful to binge-watch these valuable resources to quickly enhance their skills. Make sure to seize this opportunity, as it will undoubtedly aid your growth and learning experience.

Contenda image

To further enhance your app, head back to the map screen and navigate to the NavigateCard. Inside the NavigateCard, add a new View component beneath the existing content. This new View will include a button for selecting different rides options.

<View>
  {/* Add your rides button here */}
</View>

By incorporating this feature, you provide users with more flexibility in choosing their preferred ride options and improve the overall user experience.

Contenda image

With the current layout, you have a rides button, and you want to add another button for Uber Eats. To achieve this, create a View component underneath the existing content inside the NavigateCard. Inside this new View, add two TouchableOpacity components – one for rides and one for Uber Eats. This setup mimics the design and functionality of the standard Uber app, providing users with more flexibility in choosing their preferred options.

<View>
  <TouchableOpacity>
    {/* Rides Button */}
  </TouchableOpacity>
  <TouchableOpacity>
    {/* Uber Eats Button */}
  </TouchableOpacity>
</View>

By incorporating these buttons, you improve the overall user experience, as users can easily switch between ride and food delivery options. And, if you enjoy the React Basics content on Skillshare, please consider leaving a positive review to help other students discover the course, which in turn supports the growth of the platform and its instructors.

Contenda image

Enhancing the App's Design and Functionality with Advanced Web Development Concepts

As Arthur suggests, it's essential to keep grinding and expanding your knowledge in various areas of web development. Focusing on CSS and React concepts, such as Redux and Mojito, can significantly enhance your skillset. In fact, this particular build incorporates a lot of Redux, which might make it seem intimidating. However, delving into these advanced concepts will help you become a more well-rounded developer and tackle more complex projects with ease. So, continue to challenge yourself and explore different aspects of web development to boost your expertise and proficiency.

Contenda image

To build upon the NavigateCard, add a new View component inside it. Within this View, create a TouchableOpacity component that includes an Icon and some text. The Icon will come from Font Awesome and represent a car with a white color and size 16. Use Tailwind styling for the text, making it white and centered, with the content saying "rides". Don't forget to add the necessary imports for the Icon and TouchableOpacity components. Your code should now resemble this:

<View>
  <TouchableOpacity>
    <Icon name="car" color="white" size={16} />
    <Text style={styles.text}>rides</Text>
  </TouchableOpacity>
</View>

With this addition, users can now interact with the "rides" button, further improving the app's functionality and user experience.

Contenda image

Now, let's modify the TouchableOpacity component to include a background color and improve the button's appearance. Start by adding a style attribute to the TouchableOpacity component, with the following styling options: flex, flex-row, bg-black, w-24, px-4, py-3, and rounded-4. These styles will make the button look better and more prominent. Here's the updated code for your TouchableOpacity component:

<TouchableOpacity style={Tailwind('flex flex-row bg-black w-24 px-4 py-3 rounded-4')}>
  <Icon name="car" color="white" size= />
  <Text style=>rides</Text>
</TouchableOpacity>

Thanks to Tailwind, you can quickly create a sleek and well-designed button with minimal effort. The updated "rides" button is now visible and has a more polished appearance, enhancing the user experience in your app.

Contenda image

With the "rides" button in place, you can quickly create a similar button for Uber Eats by copying the TouchableOpacity component and making a few adjustments. Replace the bg-black styling with a transparent background and change both the icon and text colors to black instead of white. This will give you a visually appealing button that contrasts nicely with the "rides" button. The updated code should look like this:

<TouchableOpacity>
  <Icon name="car" color="black" size= />
  <Text style=>Uber Eats</Text>
</TouchableOpacity>

By default, the View component stacks its children in a column, which is why the buttons are displayed one above the other. With these changes, users can easily switch between ride and food delivery options, improving the overall user experience.

Contenda image

To style the View component, set its style attribute to use Tailwind with the following styles: flex-row, bg-white, justify-evenly, py-2, mt-auto, border-t, and border-gray-100. This will arrange the child components in a row, create even spacing between them, add padding on the vertical axis, push the content to the bottom, and apply a border at the top. Your updated code should look like this:

<View style={Tailwind`flex-row bg-white justify-evenly py-2 mt-auto border-t border-gray-100`}>
  ...
</View>

With these styling changes, your app's layout will be more polished and visually appealing. It's essential to have a great coding playlist to keep you motivated and focused while developing your app, so keep enjoying your coding sessions and continue enhancing your app's design and functionality!

Contenda image

Now, with the added border at the top, the layout looks even better. However, the "rides" button appears a bit squashed. To fix this issue, you might need to adjust the styles applied to the TouchableOpacity component. Keep refining your app's design and functionality to achieve the best possible user experience. Remember, having a great coding playlist can help you stay motivated and focused during development sessions. So, keep enjoying your coding sessions and continue enhancing your app!

Contenda image

To fix the squashed appearance of the "rides" button, you will need to add the justify-between style to the TouchableOpacity component containing the icon. This style creates space between the elements inside the component, improving the layout. Update the TouchableOpacity component with the justify-between style as shown:

<TouchableOpacity style=>
  <Icon name="car" color="white" size= />
  <Text style=>rides</Text>
</TouchableOpacity>

Now, the "rides" button looks better and well-spaced, enhancing the overall layout and user experience. Make sure to keep refining your app's design and functionality to achieve the best possible user experience.

Contenda image

To enable navigation to the next screen when the "rides" button is pressed, add an onPress attribute to the TouchableOpacity component. This attribute will trigger the navigation.navigate function, which requires the navigation prop to be imported. Set the onPress attribute to navigate to the RideOptionsCard screen. Your updated TouchableOpacity component should look like this:

<TouchableOpacity onPress={() => navigation.navigate('RideOptionsCard')}>
  <Icon name="car" color="white" size= />
  <Text style=>rides</Text>
</TouchableOpacity>

Now, when users click on the "rides" button, they will be taken to the next screen, further improving the app's functionality and user experience.

Contenda image

Enhancing Ride Selection Interface and Functionality

With the current layout, the app now displays a "Select a Ride" header at the top of the screen, followed by a flat list of car options. The data for these options includes unique IDs, titles, and cost multipliers. For example, UberX has a multiplier of 1, UberXL has a multiplier of 1.2, and UberLux has a multiplier of 1.75. Each option also has a corresponding image.

To add the back button functionality, wrap the TouchableOpacity component containing the Chevron left icon from Font Awesome in a View component. Then, use absolute positioning with Tailwind to place the button at the desired location. When pressed, the back button should navigate to the previous screen. To achieve this, use the navigation.navigate() function, passing the name of the previous screen, which in this case is the NavigateCard.

The next step is to render a list of car options using the FlatList component. Make sure to import it and set the data attribute to the car options data created earlier. This will display the available ride options, such as UberX, UberXL, and UberLux, along with their respective cost multipliers and images.

Contenda image

To display the car options in a list, use the FlatList component. First, pass the car options data to the data attribute of the FlatList. Then, set the keyExtractor attribute to extract the keys from the items' IDs. To render each item in the list, use the renderItem attribute, which takes an arrow function that deconstructs the item from the list.

Inside the arrow function, use a TouchableOpacity component to display each car option. Initially, add a Text component inside the TouchableOpacity with the text "car" to see if three cars are rendered on the screen.

<FlatList
  data={...}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => (
    <TouchableOpacity>
      <Text>car</Text>
    </TouchableOpacity>
  )}
/>

Now that you can see the three car options, replace the Text component with an Image component to display the actual car images. Set the image's style attribute to have a width and height of 100 and set the resizeMode to "contain" to maintain the aspect ratio. Finally, set the source attribute to the image of the current item in the list.

<Image
  style={{
    width: 100,
    height: 100,
    resizeMode: 'contain',
  }}
  source={{ uri: item.image }}
/>

With these changes, the car options are now displayed as images in the list, making it easier for users to choose the desired ride option. Keep refining your app's design and functionality to provide the best possible user experience.

Contenda image

To destructure the item and display the title, multiplier, and image, you can use the following code inside the renderItem arrow function of the FlatList component:

const { id, title, multiplier, image, ...item } = item;

With this destructuring, you can still access the full item object. Next, replace the "car" text inside the TouchableOpacity with an Image component displaying the car images. Set the image's style attribute to have a width and height of 100 and set the resizeMode to "contain" to maintain the aspect ratio. Set the source attribute to the image of the current item in the list:

<Image
  style={{ width: 100, height: 100, resizeMode: 'contain' }}
  source={{ uri: image }}
/>

Then, create a View component containing two Text components to display the title and an estimated travel time, such as "UberX, travel time...". Style the TouchableOpacity with Tailwind to arrange the elements in a row, center them, and justify the items between themselves. Add padding, font size, and other styles to refine the appearance.

To keep track of the selected car option, create a piece of state called selected and use the setSelected function to update it when a car option is clicked:

const [selected, setSelected] = useState(null);

In the onPress attribute of the TouchableOpacity, set the selected item:

<TouchableOpacity onPress={() => setSelected(item)}>

Now, conditionally apply a background color to the selected car option by comparing the ID of the current item with the selected item's ID:

style={tailwind(`... ${id === selected?.id ? 'bg-gray-200' : ''}`)}

With these changes, the car options are displayed as images in a list, and users can select their desired ride option. Keep refining your app's design and functionality to provide the best possible user experience.

Contenda image

Now, when selecting a car option, you'll notice that the background color changes, indicating the selected car. This forms the basis of the button functionality. Combining Tailwind, React Native, and the previous changes, you can further refine the appearance of the button. To center the text, set the text color to white, and increase the font size, use the following Tailwind classes:

style={`text-center text-white text-xl`}

This will ensure that the text is centered, white, and has an extra-large font size. Keep refining your app's design and functionality to provide the best possible user experience.

Contenda image

Enhancing Button Appearance and Functionality in Your App

To improve the appearance of the button, you can set its background color to black and add padding and margin to create some space around it. Use the Tailwind utility classes for this purpose. For example, you can set the background color to black with bg-black, add padding on the Y-axis with py-3, and set a margin of 3 with m-3. By doing so, the button looks better and more visually appealing. This ensures that the button is not touching the edges of the screen, and because it's within the safe area, it won't be obstructed by any device-specific elements.

style={Tailwind('bg-black py-3 m-3')}

Feel free to continue refining your app's design and functionality to provide the best possible user experience for your users.

Contenda image

To further enhance your app, don't forget to register for the upcoming React to Airbnb challenge happening next Tuesday. This event will span five days and involve coding React in Airbnb. With £10,000 worth of prizes up for grabs, it's an excellent opportunity for both newcomers and experienced developers to learn and have fun. Make sure to sign up using the registration link provided and join this exciting event.

Contenda image

To make the button disabled when no car option is selected, add a disabled attribute to the TouchableOpacity component. Set its value to true when there is no selected item:

<TouchableOpacity disabled=>

Additionally, conditionally apply a grey background to the button when there is no selected item by using the bg-grey-300 Tailwind class:

style=`)}

Now, when navigating back and forth between screens, the button will appear disabled and have a grey background until a car option is selected. Once an option is chosen, the button becomes enabled and changes its background color. This enhances the app's user experience by clearly indicating when the button is active and usable. Keep refining your app's design and functionality to provide the best possible user experience.

Contenda image

Integrating Google Distance Matrix API for Enhanced Functionality and User Experience

To complete the build, we'll integrate the Google Distance Matrix API, which allows us to calculate the total distance from point A to point B. This enables users to select a ride with the distance in miles, get an estimated time for reaching the destination, and use the relevant information from the distance matrix to calculate a price that can be charged to the customer. Integrating this API will enhance the app's functionality and provide more valuable information to users, making their experience even better.

Contenda image

With the current implementation, the next step is to manage the logic for the Google Distance Matrix API integration. As the necessary details are stored around the map, it makes sense to handle this logic inside the Map component. This integration will allow the app to calculate the total distance between two points, provide an estimated travel time, and offer a calculated price based on the selected ride option. By incorporating the Google Distance Matrix API, you enhance the app's functionality and deliver a more valuable experience to users.

Contenda image

Create a useEffect that is responsible for calculating the travel time. This useEffect will depend on the origin, destination, and the Google Maps API key. By making the useEffect dependent on these variables, you ensure that the travel time is accurately calculated whenever any of these values change.

useEffect(() => {
  // Calculate the travel time here
}, [origin, destination, googleMapsApiKey]);

Contenda image

Integrating Google Distance Matrix API and Managing Travel Time Data with Redux

With the app layout displaying a "Select a Ride" header and a list of car options, it's time to enhance its functionality by integrating the Google Distance Matrix API. This API allows for calculating the travel time between the origin and destination. Since the request to the API is asynchronous, you'll need to handle it accordingly.

To manage this integration, create a useEffect that is responsible for calculating the travel time. This useEffect should depend on the origin, destination, and the Google Maps API key. By making the useEffect dependent on these variables, you ensure that the travel time is accurately calculated whenever any of these values change.

useEffect(() => {
  // asynchronous code for the Google Distance Matrix API request
}, [origin, destination, googleMapsApiKey]);

By incorporating the Google Distance Matrix API, you not only enhance the app's functionality but also provide a more valuable experience to users. Continue refining your app's design and functionality to deliver the best possible user experience.

Contenda image

Now, you should push the calculated travel time into Redux. This way, you can access it in the other component – the one where users select a ride – by using the travel time selector. This approach allows you to seamlessly share data between components, ensuring that relevant information is available when needed, resulting in a better user experience.

Contenda image

In order to calculate the travel time within the useEffect, you'll need to create an asynchronous function, getTravelTime, inside the useEffect and then invoke it. You can't use async directly inside useEffect since it breaks the rules of hooks. To create an asynchronous block of code, define the getTravelTime function inside the useEffect and then call it like so:

useEffect(() => {
  const getTravelTime = async () => {
    // Your asynchronous code here
  };

  getTravelTime();
}, [origin, destination, googleMapsApiKey]);

By following this approach, you can execute asynchronous code within your useEffect without violating any rules of hooks. This will allow you to integrate the Google Distance Matrix API and calculate the travel time, ultimately enhancing the app's functionality and user experience. Keep refining your app's design and functionality to provide the best possible user experience.

Continuing with the integration of the Google Distance Matrix API, it's crucial to add a safeguard to ensure that the API is only called when both origin and destination are defined. To do this, you can include a condition at the beginning of the useEffect:

if (!origin || !destination) return;

This check ensures that the API call is only made when the origin and destination are available. You can place this line inside the getTravelTime function or at the beginning of the useEffect.

The API call itself is made using a fetch request, which is essentially a GET request to the Google API. By incorporating this safeguard and making the API call, you further enhance the app's functionality and user experience. Keep refining your app's design and functionality to provide the best possible user experience.

In order to make a request to the Google Distance Matrix API, you'll need to construct a query URL. The base URL for the API call is:

https://maps.googleapis.com/maps/api/distancematrix/json

You can use template literals (backticks) to interpolate JavaScript values into the URL. Set the units parameter to imperial and pass the origin, destination, and key (Google Maps API key) as parameters:

const url = `https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=${origin.description}&destinations=${destination.description}&key=${googleMapsApiKey}`;

Here, the origin and destination values are obtained from Redux. By making a fetch request to this URL, you can retrieve the travel time information, further enhancing the app's functionality and user experience. Continue refining your app's design and functionality to provide the best possible user experience.

To fetch the travel time information from the Google Distance Matrix API, you can use the fetch function to make a request to the constructed query URL. Once the request is made and a response is received, you'll need to parse the response as a JSON object. Here's how you can do that:

fetch(url)
  .then(response => response.json())
  .then(/* handle the JSON object */);

By fetching and handling the travel time information from the API, you further enhance your app's functionality and user experience. Continue refining your app's design and functionality to provide the best possible user experience.

After fetching the travel time information from the Google Distance Matrix API, you can access the data using .then(). This data contains valuable information, such as the time it takes to travel from point A to point B.

fetch(url)
 .then(response => response.json())
 .then(data => {
   // handle the data object
 });

By handling the data returned from the API, you're able to further enhance your app's functionality and provide a better user experience. Continue refining your app's design and functionality to deliver the best possible experience for your users.

Now that the travel time information has been fetched from the Google Distance Matrix API, it's time to dispatch the data to Redux. To demonstrate that the data is being fetched correctly, you can log the data to the console:

fetch(url)
  .then(response => response.json())
  .then(data => {
    console.log(data);
  });

Upon logging the data, you can see the destination, origin, distance, and travel time. There's also a valuable value available that can be used to calculate the price. With this information in hand, you've successfully integrated the Google Distance Matrix API into your app. This not only enhances the app's functionality but also provides a more valuable experience to users. Continue refining your app's design and functionality to deliver the best possible user experience.

To store the travel time information in Redux, you'll need to use a dispatch. First, get the dispatch by declaring a variable dispatch and assigning it to useDispatch(). Then, call the dispatch function with the action setTravelTimeInformation:

const dispatch = useDispatch();
// ...
fetch(url)
  .then(response => response.json())
  .then(data => {
    dispatch(setTravelTimeInformation(data));
  });

By storing the travel time information in Redux, you enable seamless sharing of data between components, ensuring relevant information is available when needed and resulting in an improved user experience. Keep refining your app's design and functionality to provide the best possible experience for your users.

Now that you've fetched the travel time information from the Google Distance Matrix API, you only want to extract the relevant data to store in Redux. To save you some time, you can access the required information directly by navigating through the returned object like this:

const relevantData = data.rows[0].elements[0];

This line of code extracts the necessary information from the API response, which includes the travel time, distance, and other valuable data. With this information extracted, you can now dispatch it to Redux and continue refining your app's design and functionality to provide an improved user experience.

With the travel time information obtained and dispatched to the Redux global store, you can now access this data from any component in your application. This ensures seamless sharing of information between components, enhancing the overall user experience. Continue making improvements to your app's design and functionality to provide the best possible experience for your users.

In the RideOptions component, you can access the travel time information stored in Redux. To do this, create a variable called travelTimeInformation and use the useSelector hook from React Redux to select the travel time information. Make sure to import useSelector and selectTravelTimeInformation from their respective modules. Here's how you can do it:

import { useSelector } from 'react-redux';
import { selectTravelTimeInformation } from '../path/to/navSlice';

// Inside the RideOptions component
const travelTimeInformation = useSelector(selectTravelTimeInformation);

By utilizing the useSelector hook and selecting the travel time information from Redux, you can now access this data within the RideOptions component. This enables seamless sharing of information between components, further enhancing the user experience. Keep improving your app's design and functionality to provide the best possible experience for your users.

Enhancing User Experience with Travel Time and Distance Information

Inside the RideOptions component, you now have access to the travel time information, which allows you to display the selected ride and its corresponding travel time. To do this, inside the component, you can use the following code:

const displayText = `Selected Ride - Travel Time: ${travelTimeInformation?.distance?.text}`;

This code creates a string called displayText which includes the travel time and distance information from the travelTimeInformation object. By utilizing this information, you can enhance the user experience by providing them with the relevant details about their chosen ride. Keep improving your app's design and functionality to provide the best possible experience for your users.

Inside the RideOptions component, you can now display the distance information for the selected ride by accessing the distance.text property of the travelTimeInformation object. For example, if you want to display the distance between London and Essex, the output will show "32.6 miles" as the distance. By incorporating this information into your app, you can provide users with more accurate and helpful details about their chosen rides, further enhancing the overall user experience. Keep refining your app's design and functionality to offer the best possible experience for your users.

Now, let's display both the travel time and distance in the displayText string. Instead of just showing the travel time, you can also include the distance by accessing the distance.text property from the travelTimeInformation object. Here's how you can update the displayText string:

const displayText = `Selected Ride - Travel Time: ${travelTimeInformation.duration.text} - Distance: ${travelTimeInformation.distance.text}`;

This will display both the travel time and distance for the selected ride. For instance, when selecting a ride from London to Germany, it will show "10 hours, 24 minutes" as the travel time and "53 miles" as the distance. With this additional information, your app becomes even more informative and useful for your users. As always, continue refining your app's design and functionality to provide the best possible experience for your users.

Now you're ready to calculate the price for the ride based on the distance and travel time. Stay tuned for the final piece of the puzzle!

Calculating Ride Price and Improving Navigation

To calculate the price for the ride based on distance and travel time, you can use a custom formula. First, create a constant representing a surge charge rate, which can be modified based on demand:

const surgeChargeRate = 1.5;

Next, use the Internationalization JavaScript API to format the price. This built-in API allows you to format a piece of text using your custom formula. The formula calculates the price based on the travel time duration value, the surge charge rate, and each car's multiplier:

const price = new Intl.NumberFormat('en-GB', {
  style: 'currency',
  currency: 'GBP',
}).format(
  (travelTimeInformation?.duration?.value * surgeChargeRate * carMultiplier) / 100
);

Now, you can display the price alongside the travel time and distance in the displayText string:

const displayText = `Selected Ride - Travel Time: $ - Distance: $ - Price: ${price}`;

This will display the travel time, distance, and calculated price for the selected ride, providing users with a more informative and useful app. Keep refining your app's design and functionality to offer the best possible experience for your users. With all the features implemented, you now have a powerful Uber clone app built using React Native, Tailwind, and React Redux.

To make the icon pop out, set its background color to bg-gray-100 and give it a Z-index of 50, which determines the layering order on the screen. Add some padding with p-3 and round the corners using rounded-4. To add a shadow behind the icon, use shadow-lg. Now you should see a nice floating icon above everything else.

For navigation, first import the useNavigation hook from React Navigation. Create a constant navigation and assign it to the useNavigation() function. When the icon is pressed, add an arrow function to navigate to the home screen by calling navigation.navigate("HomeScreen").

For example, let's say you want to navigate from Mumbai, India to another location. By implementing these changes, your app's navigation should now function smoothly, allowing users to select different locations with ease. Keep refining your app's design and functionality to provide the best possible experience for your users.

Resolving Errors and Enhancing the Uber Clone App

In this section, we encountered an issue when trying to calculate the travel time and distance from Mumbai to Dubai. The error was caused by an undefined value in the travelTimeInformation object. To protect against this, you can use optional chaining while accessing the properties of the object. For example, update the displayText string as follows:

const displayText = `Selected Ride - Travel Time: ${travelTimeInformation?.duration?.text} - Distance: ${travelTimeInformation?.distance?.text}`;

By doing this, we managed to resolve the error and successfully display the travel time and distance between different locations, including Mumbai to Dubai, and London to New Delhi. Remember, when encountering errors, it's crucial to keep calm, analyze the issue, and use your developer toolkit to find a solution.

In conclusion, we've built an impressive Uber clone app using React Native, Tailwind, and React Redux with features such as travel time, distance, and price calculation. Always strive to refine your app's design and functionality to provide the best possible experience for your users. Keep learning and improving your skills as a developer to tackle any challenges that come your way.

Explore the Uber Clone App and Expand Your Developer Skills with Upcoming Challenges and Courses

In this demo, we've showcased an Uber clone app that uses the Google Places API, Google Directions API, and Google Distance Matrix API. These APIs power features like autocomplete for location input, directions between two points, and calculating travel time and distance. The app has a sleek user interface with well-integrated UI elements.

For example, if you search for "London Bridge" and select "Get a Ride," the app will display the origin as London Bridge. You can then click on "Where to?" and input "Birmingham, UK" as your destination. The app will show the estimated cost of the ride as £132, with a distance of 127 miles. You can interact with the map, switch between origin and destination, and even select different ride options.

The app also includes optional styling, swiping functionality between screens, and a floating button to return to the home page. This demo highlights the power of combining various APIs with React Native, Tailwind, and React Redux to create a well-designed, feature-rich, and user-friendly app. Keep refining your app's design and functionality to provide the best possible experience for your users.

After completing the Uber clone app, you might be interested in deploying it. Deploying React Native apps is a different process altogether, so it's worth considering a separate video to cover that topic. In the meantime, share your progress on Instagram by tagging @SSSSanga and sharing your experience with the project.

If you enjoyed this tutorial and want to take part in more learning opportunities, there's an upcoming challenge at PapaReact.com with only a few days left before it begins. The five-day React challenge offers over £10,000 worth of prizes and covers a wide range of topics, including creating a portfolio, front-end build, calendar search functionality, Mapbox integration, and a React and Next.js build. As a bonus, you'll receive a 60-page book written by Sanga, valued at £50, for free when you sign up and participate in the challenge. Don't miss this opportunity to expand your knowledge and improve your skills as a developer!

In addition to the impressive Uber clone app, there are more learning opportunities available to help you further improve your skills as a developer. One such opportunity is the upcoming challenge at PapaReact.com, offering over £10,000 worth of prizes and covering various topics like creating a portfolio, front-end build, calendar search functionality, Mapbox integration, and a React and Next.js build. Make sure to reserve your spot, as seats are limited.

Furthermore, there is an exclusive Skillshare opportunity available, providing free access to the React Basics 101 class. This course covers all the fundamentals of React, and you can access it through the second link in the description for a free month. Don't miss these opportunities to expand your knowledge and become a better developer.

The Uber clone app built using React Native, Tailwind, and React Redux showcases the potential of combining various technologies and APIs to create a feature-rich, well-designed, and user-friendly application. If you're looking to further enhance your skills as a developer, consider participating in the upcoming challenge at PapaReact.com or check out the Zero to Full Stack Hero course.

These learning opportunities cover a wide range of topics, from creating a portfolio and front-end build to calendar search functionality, Mapbox integration, and React and Next.js build. Additionally, there's a free Skillshare course called React Basics 101, accessible through the second link in the description, which covers all the fundamentals of React. Don't miss out on these chances to expand your knowledge and become an even better developer.

In conclusion, the Uber clone app developed using React Native, Tailwind, and React Redux demonstrates the power of combining multiple technologies and APIs to create a feature-rich, well-designed application. With over 2,000 likes on the video and 30,000+ playbacks, it's evident that this was the biggest build ever done on the channel.

As a developer, never miss an opportunity to learn and grow. Make sure to register for the upcoming challenge at PapaReact.com and attend the Airbnb challenge next Tuesday. Keep pushing yourself to become better and continue expanding your knowledge. Stay tuned for more exciting content, and as always, see you in the next one!

papareact's People

Contributors

donfrancisco avatar

Stargazers

Yash Gupta avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.