<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Colin Hale</title>
    <description>The latest articles on DEV Community by Colin Hale (@colinah).</description>
    <link>https://dev.to/colinah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1092609%2Fc009f290-61ea-43ea-be8b-74f861a82916.jpeg</url>
      <title>DEV Community: Colin Hale</title>
      <link>https://dev.to/colinah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/colinah"/>
    <language>en</language>
    <item>
      <title>Creating Accessible Custom Components with React Aria: A Practical Example with Forms</title>
      <dc:creator>Colin Hale</dc:creator>
      <pubDate>Tue, 18 Jul 2023 22:12:07 +0000</pubDate>
      <link>https://dev.to/colinah/creating-accessible-custom-components-with-react-aria-a-practical-example-with-forms-1cp9</link>
      <guid>https://dev.to/colinah/creating-accessible-custom-components-with-react-aria-a-practical-example-with-forms-1cp9</guid>
      <description>&lt;p&gt;As web developers, it is crucial to prioritize accessibility in our applications. In this blog post we will dive into how we can create custom components with react-aria hooks to make accessible components. React-aria separates the behavior and accessibility implementation for common UI components into React Hooks. This makes it easy to get the behavior, accessibility and internationalization for free. Using react-aria allows you to build components more quickly and ensures that they will work well across mouse, touch, and keyboard interactions as well as with screen readers, and other assistive technology. &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Get Started!
&lt;/h2&gt;

&lt;p&gt;React Aria leverages the power of React hooks to seamlessly integrate accessibility into components. To incorporate accessibility into a component, there are two main steps. Firstly, you need to obtain a reference to the component you want to enhance with accessibility features. For example, if you have a button component, you can use the useButton hook from React Aria to access its accessibility-related functionalities. Secondly, you can spread the props provided by the useButton hook into the component to ensure accessibility support. This approach ensures that the component is properly enhanced and adheres to accessibility standards.&lt;/p&gt;

&lt;p&gt;Here is the example component from my &lt;a href="https://codesandbox.io/s/react-aria-example-t37s7m?file=/src/components/Button.tsx:1135-1467"&gt;codesandbox&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function ThemedButton(props: Props) {
  const ref = useRef();
  const { buttonProps } = useButton(props, ref);
  return (
    &amp;lt;Button
      ref={ref}
      {...buttonProps}
      text="#ffffff"
      color={colors.primary}
      style={props.style ? props.style : null}
    &amp;gt;
      {props.text}
    &amp;lt;/Button&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our custom button component set up, we can utilize it to leverage the accessibility features provided by React Aria. By using this component, we can effortlessly incorporate essential accessibility functionality without the need for manual implementation. Let's take a look at an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Usage example:
function App() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Button onClick={() =&amp;gt; console.log('Button clicked!')}&amp;gt;
        Click Me
      &amp;lt;/Button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, this blog post provided a concise demonstration of how React Aria hooks can be utilized to enhance the accessibility of a custom button component. However, there are many more exciting possibilities to explore with React Aria for implementing accessibility in various components and scenarios. I encourage you to visit my &lt;a href="https://codesandbox.io/s/react-aria-example-t37s7m"&gt;CodeSandbox&lt;/a&gt; example where you can delve deeper into the world of accessibility-driven development. Feel free to experiment, modify the code, and adapt it to suit your specific requirements. Let's embark on this journey together, continuously striving to build inclusive and accessible web applications. Together, we can create a more inclusive digital experience for all users.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a Simple React Typescript CRUD App: Interview Question</title>
      <dc:creator>Colin Hale</dc:creator>
      <pubDate>Thu, 29 Jun 2023 16:03:34 +0000</pubDate>
      <link>https://dev.to/colinah/building-a-simple-react-typescript-crud-app-interview-question-lg</link>
      <guid>https://dev.to/colinah/building-a-simple-react-typescript-crud-app-interview-question-lg</guid>
      <description>&lt;p&gt;During a recent interview, I was presented with an intriguing challenge: create a basic CRUD (Create, Read, Update, Delete) application using React and Typescript. I found this task to be both engaging and enjoyable, so I decided to share my solution with you. In this blog post, I'll walk you through the process of building a simple CRUD app with only front-end functionality. Additionally, I'll demonstrate how to persist the app's state using local storage, enabling data retention even when the user refreshes their browser. Although error handling has been simplified through alert messages for the sake of simplicity, you can easily enhance it later on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the CRUD App:
&lt;/h2&gt;

&lt;p&gt;To start, I approached the task by designing a custom hook that would handle all the necessary functionality. This hook would encapsulate the logic for creating, reading, updating, and deleting data, allowing us to easily access the required functions. To provide a seamless user experience, it's essential to preserve the application's state even when the browser is refreshed. To achieve this, I utilized the local storage feature available in modern web browsers. By leveraging the local storage API, we can store the app's data and retrieve it when needed, ensuring continuity between sessions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const useCRUD = () =&amp;gt; {
  const [items, setItems] = React.useState([] as string[]);

  const setItemsWithStorage = (items: string[]) =&amp;gt; {
    setItems(items);
    localStorage.setItem("items", JSON.stringify(items));
  };

  React.useEffect(() =&amp;gt; {
    const items = localStorage.getItem("items");
    if (items) {
      setItems(JSON.parse(items));
      // Also get from backend here
    }
  }, []);

  const addItem = (item: string) =&amp;gt; {
    if (items.includes(item)) {
      alert("List already contains item");
      return;
    }
    setItemsWithStorage([...items, item]);
    // Also add to backend
  };

  const deleteItem = (item: string) =&amp;gt; {
    if (!items.includes(item)) {
      alert("Item not in list");
      return;
    }
    const filtered = items.filter((v) =&amp;gt; v !== item);
    setItemsWithStorage(filtered);
    // Also add to backend
  };

  const getItems = () =&amp;gt; items;

  const updateItem = (prevItem: string, newItem: string) =&amp;gt; {
    if (!items.includes(prevItem)) {
      alert("Item not in list");
      return;
    }
    if (items.includes(newItem)) {
      alert("List already contains item");
      return;
    }
    const newItems = items.map((i) =&amp;gt; (i === prevItem ? newItem : i));
    setItemsWithStorage(newItems);
    // Also update in backend
  };
  return { addItem, deleteItem, getItems, updateItem };
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this project presents a simplified version designed to demonstrate the proof of concept during an interview, I thoroughly enjoyed the process and saw it as an excellent opportunity to showcase my skills. I would love to hear your thoughts on how you would approach this problem. Would you have also opted for a custom hook, or would you have pursued a different approach? Please share your insights in the comments below; I'm eager to learn from your perspective. I hope this tutorial has been valuable to you in your journey of building React Typescript CRUD apps.&lt;/p&gt;

&lt;p&gt;You can find my example here: &lt;a href="https://codesandbox.io/s/simple-crud-app-2lxj6k?file=/src/App.tsx"&gt;https://codesandbox.io/s/simple-crud-app-2lxj6k?file=/src/App.tsx&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Learning Firebase and React-Native: Private Message App</title>
      <dc:creator>Colin Hale</dc:creator>
      <pubDate>Fri, 16 Jun 2023 03:47:44 +0000</pubDate>
      <link>https://dev.to/colinah/learning-firebase-and-react-native-private-message-app-3n06</link>
      <guid>https://dev.to/colinah/learning-firebase-and-react-native-private-message-app-3n06</guid>
      <description>&lt;p&gt;In this tutorial I show you what I learned along my journey to test out making a simple test application creating a private messaging app. I won't be covering the firebase authentication process found in the app. That was covered in a previous post here: &lt;a href="https://dev.to/colinah/learning-firebase-and-react-native-authentication-2822"&gt;https://dev.to/colinah/learning-firebase-and-react-native-authentication-2822&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While thinking of ways to build this out, I wanted to make the private chat system flexible so if I wanted to change that chat into a group chat the architecture would already be set up. To do this there was a couple of things to consider. Firstly how we are going to store the data for the messages, what data we need and how to have users tied to that data.&lt;/p&gt;

&lt;p&gt;To store the messages I decided to go with a Firebase collection named rooms, that would have a unique key generated by the combination of the two users id's. Then the room document would contain the following properties, color, lastMessage, messages, and users. Where color is a string hex code for a color to assign the group, lastMessage is the last message that was sent in the chat to display on the list of chats screen, messages is an array of messages in the room, and lastly users is the an array of people in the room. Here is an example of a rooms document.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AKlA2K7I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ykw0s0xtmr7bhsy5udl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AKlA2K7I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ykw0s0xtmr7bhsy5udl.png" alt="Image description" width="584" height="1161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also need a way for each user to know what chats/rooms they have already started to display in the messages screen. I decided to store the room id's in the user object in an array.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K-LwD6ag--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ubj6ujxzrqj4018osqdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K-LwD6ag--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ubj6ujxzrqj4018osqdx.png" alt="Image description" width="581" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know what the firebase data base will look like with this project let's get started on the React-Native application.   &lt;/p&gt;

&lt;p&gt;There are three main screens for the chat portion of the application, chats, messages and newChat. The chats screen displays a list of the rooms the user is in, the messages screen displays the messages sent between the two users, and lastly the newChat screen allows the user to search for users to start a chat with.&lt;/p&gt;

&lt;p&gt;Let's start with building the chat screen. We want to subscribe to the users firebase user object that way the rooms will automatically update if there is a change. Here is what the Chats Component looks like the ChatGroup component is a simple display showing the name of the people in the chat and the last message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function Chats() {
  const [rooms, setRooms] = React.useState([]);
  const { user } = useContext(UserContext);
  const router = useRouter();

  React.useEffect(() =&amp;gt; {
    const userRef = doc(firestore, 'users', user.uid);

    const unSub = onSnapshot(userRef, (doc) =&amp;gt; {
      doc.exists() &amp;amp;&amp;amp; setRooms(doc.data().rooms);
    });

    return () =&amp;gt; {
      unSub();
    };
  }, []);

  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;ScrollView&amp;gt;
        {rooms ? (
          rooms.map((room) =&amp;gt; &amp;lt;ChatGroup roomId={room} key={room} /&amp;gt;)
        ) : (
          &amp;lt;View
            style={{
              padding: 6,
              borderRadius: 6,
              borderWidth: 1,
              borderColor: '#ffffff60',
              margin: 20,
            }}&amp;gt;
            &amp;lt;Text&amp;gt;You aren't in any rooms. Press the "+" to start a chat.&amp;lt;/Text&amp;gt;
          &amp;lt;/View&amp;gt;
        )}
      &amp;lt;/ScrollView&amp;gt;
      &amp;lt;FAB icon="plus" style={styles.fab} onPress={() =&amp;gt; router.push('/(chat)/newChat')} /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next screen is the messages screen. To add a bit more functionality easier I decided to go with the react-native-gifted-chat package which handles displaying the messages. To get the messages we need to subscribe to the rooms document the same way we did for the user object. This will keep the messages up to date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function Messages() {
  const [messages, setMessages] = React.useState&amp;lt;IMessage[]&amp;gt;([]);
  const { user } = React.useContext(UserContext);
  const { id } = useSearchParams();

  React.useEffect(() =&amp;gt; {
    const roomRef = doc(firestore, 'rooms', id as string);

    const unSub = onSnapshot(roomRef, (doc) =&amp;gt; {
      doc.exists() &amp;amp;&amp;amp;
        setMessages(
          doc.data().messages.map((message: any) =&amp;gt; ({
            ...message,
            createdAt: message.createdAt.toDate(),
          }))
        );
    });

    return () =&amp;gt; {
      unSub();
    };
  }, [id]);

  const onSend = async (messages: IMessage[]) =&amp;gt; {
    const roomRef = doc(firestore, 'rooms', id as string);
    await updateDoc(roomRef, {
      messages: arrayUnion(messages[0]),
      lastMessage: messages[0],
    });
  };

  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;Stack.Screen
        options={{
          title: 'Messages',
        }}
      /&amp;gt;
      &amp;lt;GiftedChat
        renderBubble={ThemedBubble}
        renderInputToolbar={ThemedInputToolbar}
        minInputToolbarHeight={60}
        messages={messages.reverse()}
        showAvatarForEveryMessage
        onSend={(messages) =&amp;gt; onSend(messages)}
        user={{
          _id: user ? user.uid : 'Not logged it',
          name: user ? (user.displayName as string) : 'No Display Name',
          avatar: user?.photoURL ? user.photoURL : '',
        }}
      /&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly we need a way to start new chats with users, this is handled in the newChat screen. To do this we can just have a search input that connects to the users collection and searches for users by name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function NewChat() {
  const [search, setSearch] = React.useState('');
  const [results, setResults] = React.useState&amp;lt;UserInfo[]&amp;gt;([]);

  const onSearchHandler = async (text: string) =&amp;gt; {
    setSearch(text);
    const q = query(collection(firestore, 'users'), where('displayName', '==', text.toLowerCase()));

    try {
      const querySnapshot = await getDocs(q);

      const list = [] as UserInfo[];
      querySnapshot.forEach((doc) =&amp;gt; list.push(doc.data() as UserInfo));
      setResults(list);
    } catch (err) {
      console.log('error', err);
    }
  };

  return (
    &amp;lt;View style={{ flex: 1 }}&amp;gt;
      &amp;lt;TextInput value={search} onChangeText={onSearchHandler} /&amp;gt;
      {results.map((user) =&amp;gt; (
        &amp;lt;SearchResult username={user.displayName} email={user.email} id={user.uid} key={user.uid} /&amp;gt;
      ))}
    &amp;lt;/View&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the basic framework for making a private messaging app using react native and firebase. If you want to look at the entire project you can find it here at &lt;a href="https://github.com/codingcruxes/react-native-firebase-chat"&gt;https://github.com/codingcruxes/react-native-firebase-chat&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed following along and where able to learn as much as I did along this process.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>reactnative</category>
      <category>firebase</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Learning Firebase and React Native: Authentication</title>
      <dc:creator>Colin Hale</dc:creator>
      <pubDate>Wed, 31 May 2023 21:48:59 +0000</pubDate>
      <link>https://dev.to/colinah/learning-firebase-and-react-native-authentication-2822</link>
      <guid>https://dev.to/colinah/learning-firebase-and-react-native-authentication-2822</guid>
      <description>&lt;p&gt;In this tutorial I show you what I learned along my journey to  making a simple test application to better learn Firebase and React Native. We will start a project with expo-routing. Then build the UI with react-native-paper. Then connect the UI to Firebase Authentication.&lt;/p&gt;

&lt;p&gt;To get started I want a basic React Native template that uses the expo-router package. To do that we can use their template to get started:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx create-expo-app@latest --example with-router&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After creating the project we need to use expo-router to set up our files and folder structure. The entry point for expo router is a folder named "app". At the same time we will also set up that app to use react-native-paper as our component library. First install react-native-paper.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install react-native-paper&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we need to create a theme for the project. I like to keep this in a constants folder named theme.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir constants&lt;/code&gt;&lt;br&gt;
&lt;code&gt;touch constants/theme.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open up theme.js and add the code to get started with a simple dark theme.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { DefaultTheme } from "react-native-paper";

export const theme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    primary: "#5eada6",
    secondary: "#ea568c",
    text: "#eee",
    background: "#303030",
    paper: "#424242",
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now need to set up the entry point into the application. expo-router default is set up to be at "app/index.js". We want to do some routing in the application so instead of an index.js we will make a _layout.js file that describes the stack to expo.&lt;/p&gt;

&lt;p&gt;Create the file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir app&lt;/code&gt;&lt;br&gt;
&lt;code&gt;touch app/_layouts.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Because this is the entry point of the entire app, it is a good place to set up our theme from paper. So we will import that and have the react-native-paper provider encompass out entire application. Then we will set up two different navigation pathways, (auth) and (tabs). Where auth handles the login, register and resetPassword pages and tabs would be the rest of the application in this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Stack } from "expo-router";
import { Provider as PaperProvider } from "react-native-paper";

import { theme } from "../constants/theme";

export default function RootLayout() {
  return (
    &amp;lt;PaperProvider theme={theme}&amp;gt;
      &amp;lt;Stack
        screenOptions={{
          headerStyle: { backgroundColor: theme.colors.background },
          headerTintColor: "#ffffff",
        }}
      &amp;gt;
        &amp;lt;Stack.Screen name="(auth)" options={{ headerShown: false }} /&amp;gt;
        &amp;lt;Stack.Screen name="(app)" options={{ headerShown: false }} /&amp;gt;
      &amp;lt;/Stack&amp;gt;
    &amp;lt;/PaperProvider&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the entry point for the application set up. I think it would be a good time to explain the folder structure for the rest of the project. Since we have to navigation pathways, (auth) and (tabs). This means we will need a _layout.js in each directory and then we will also put the corresponding pages in their directories as well. The completed files and folder structure will look like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkvdjmwm8ct3xt47aadl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkvdjmwm8ct3xt47aadl.png" alt="Project Folder Structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let start's here by creating the navigation components for auth and tabs.&lt;/p&gt;

&lt;p&gt;The auth navigation will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";
import { Tabs } from "expo-router";
import { useTheme } from "react-native-paper";

export default function AuthTabLayout() {
  const theme = useTheme();
  return (
    &amp;lt;Tabs
      screenOptions={{
        tabBarActiveTintColor: theme.colors.primary,
        tabBarStyle: { backgroundColor: theme.colors.background },
        headerStyle: { backgroundColor: theme.colors.background },
        headerTintColor: "#ffffff",
      }}
    &amp;gt;
      &amp;lt;Tabs.Screen
        name="index"
        options={{
          title: "Login",
          tabBarIcon: ({ color }) =&amp;gt; (
            &amp;lt;MaterialCommunityIcons
              size={28}
              style={{ marginBottom: -3 }}
              color={color}
              name="login"
            /&amp;gt;
          ),
        }}
      /&amp;gt;
      &amp;lt;Tabs.Screen
        name="register"
        options={{
          title: "Register",
          tabBarIcon: ({ color }) =&amp;gt; (
            &amp;lt;MaterialCommunityIcons
              size={28}
              style={{ marginBottom: -3 }}
              color={color}
              name="account-plus"
            /&amp;gt;
          ),
        }}
      /&amp;gt;
      &amp;lt;Tabs.Screen
        name="resetPassword"
        options={{
          title: "Reset Password",
          href: null,
        }}
      /&amp;gt;
    &amp;lt;/Tabs&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tabs navigator will be very similar to the auth one. But here we want to add a button in the header right to allow users to logout. To sign out a user in firebase we can import the signOut.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";
import { Tabs, useRouter } from "expo-router";
import { TouchableOpacity } from "react-native-gesture-handler";
import { useTheme } from "react-native-paper";
import { signOut } from "firebase/auth";
import { auth } from "../../firebaseConfig";

export default function AppTabLayout() {
  const theme = useTheme();
  const router = useRouter();

  const onLogoutHander = async () =&amp;gt; {
    await signOut(auth);
    router.replace("/");
  };
  return (
    &amp;lt;Tabs
      screenOptions={{
        tabBarActiveTintColor: theme.colors.primary,
        tabBarStyle: { backgroundColor: theme.colors.background },
        headerStyle: { backgroundColor: theme.colors.background },
        headerTintColor: "#ffffff",
      }}
    &amp;gt;
      &amp;lt;Tabs.Screen
        name="index"
        options={{
          title: "One",
          tabBarIcon: ({ color }) =&amp;gt; (
            &amp;lt;MaterialCommunityIcons
              size={28}
              style={{ marginBottom: -3 }}
              color={color}
              name="numeric-1-box"
            /&amp;gt;
          ),
          headerRight: () =&amp;gt; (
            &amp;lt;TouchableOpacity onPress={onLogoutHander}&amp;gt;
              &amp;lt;MaterialCommunityIcons
                size={28}
                style={{ marginBottom: -3 }}
                color="#fff"
                name="logout"
              /&amp;gt;
            &amp;lt;/TouchableOpacity&amp;gt;
          ),
        }}
      /&amp;gt;
      &amp;lt;Tabs.Screen
        name="screen2"
        options={{
          title: "Two",
          tabBarIcon: ({ color }) =&amp;gt; (
            &amp;lt;MaterialCommunityIcons
              size={28}
              style={{ marginBottom: -3 }}
              color={color}
              name="numeric-2-box"
            /&amp;gt;
          ),
        }}
      /&amp;gt;
    &amp;lt;/Tabs&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we haven't set up the firebase config file let's do that now. You can go to &lt;a href="https://console.firebase.google.com/u/0/" rel="noopener noreferrer"&gt;https://console.firebase.google.com/u/0/&lt;/a&gt; then start a new project. Once you have the project set up go to the authentication tab and select get started. There will be several option in this example we are using the setup authentication with email and password option. After you have that you van add your information to the config file. I called my file firebaseConfig.js but you can name this anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Import the functions you need from the SDKs you need
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';

// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: '',
  authDomain: '',
  projectId: '',
  storageBucket: '',
  messagingSenderId: '',
  appId: '',
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

export const firestore = getFirestore();

export const auth = getAuth(app);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that Authentication is enabled and we have set up our firebase files lets get to the login, register and reset password screens.&lt;/p&gt;

&lt;p&gt;For the register screen we want to use two specific function for the firebase/auth:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { createUserWithEmailAndPassword, updateProfile } from "firebase/auth";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With the createUserWithEmailAndPassword, we can generate a new user with a unqiue id when we send firebase an email and a password. After the user is created we can update the user profile with the updateProfile function. In this example we are setting the displayName to the users name. Here is what the completed register component looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createUserWithEmailAndPassword, updateProfile } from "firebase/auth";
import * as React from "react";
import { StyleSheet } from "react-native";
import { TextInput } from "react-native-paper";

import { Text, View, Button } from "../../components/Themed";
import ErrorDisplay from "../../components/ErrorDisplay";
import { auth } from "../../firebaseConfig";
import { useRouter } from "expo-router";

export default function Register() {
  const [name, setName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [confirmPassword, setConfirmPassword] = React.useState("");
  const [passwordVisible, setPasswordVisible] = React.useState(true);
  const [error, setError] = React.useState("");
  const [loading, setLoading] = React.useState(false);

  const router = useRouter();

  const registerUser = async (name) =&amp;gt; {
    setError("");
    setLoading(true);
    try {
      const res = await createUserWithEmailAndPassword(auth, email, password);

      if (auth.currentUser)
        await updateProfile(auth.currentUser, {
          displayName: name.toLowerCase(),
        });
      router.push("/(tabs)");

      setLoading(false);
    } catch (error) {
      setError(error.message);

      setLoading(false);
    }
  };

  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;Name&amp;lt;/Text&amp;gt;
        &amp;lt;TextInput
          placeholder="Name"
          value={name}
          onChangeText={(text) =&amp;gt; setName(text)}
        /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;Email&amp;lt;/Text&amp;gt;
        &amp;lt;TextInput
          placeholder="Email"
          value={email}
          onChangeText={(text) =&amp;gt; setEmail(text)}
        /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;Password&amp;lt;/Text&amp;gt;
        &amp;lt;TextInput
          secureTextEntry={passwordVisible}
          placeholder="Password"
          value={password}
          onChangeText={(text) =&amp;gt; setPassword(text)}
          right={
            &amp;lt;TextInput.Icon
              icon="eye"
              onPress={() =&amp;gt; setPasswordVisible((p) =&amp;gt; !p)}
            /&amp;gt;
          }
        /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;Confirm Password&amp;lt;/Text&amp;gt;
        &amp;lt;TextInput
          secureTextEntry={passwordVisible}
          placeholder="Confirm Password"
          value={confirmPassword}
          onChangeText={(text) =&amp;gt; setConfirmPassword(text)}
          right={
            &amp;lt;TextInput.Icon
              icon="eye"
              onPress={() =&amp;gt; setPasswordVisible((p) =&amp;gt; !p)}
            /&amp;gt;
          }
        /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Button mode="contained" onPress={() =&amp;gt; registerUser(name)}&amp;gt;
          {loading ? "Loading..." : "Register"}
        &amp;lt;/Button&amp;gt;
        &amp;lt;ErrorDisplay message={error} /&amp;gt;
      &amp;lt;/View&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
    flex: 1,
    rowGap: 20,
  },
  header: {
    padding: 6,
    borderColor: "#eeeeee60",
    borderBottomWidth: 1,
    width: "100%",
  },
  title: {
    color: "#eee",
    fontSize: 20,
    fontWeight: "bold",
  },
  separator: {
    marginVertical: 30,
    height: 1,
    width: "80%",
  },
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The login screen will be very similar to the register screen but instead of logging the user in we will be using the signInWithEmailAndPassword function from "firebase/auth". Here is the login screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRouter } from "expo-router";
import { signInWithEmailAndPassword } from "firebase/auth";
import React from "react";
import { StyleSheet, TouchableOpacity } from "react-native";
import { TextInput } from "react-native-paper";

import { Text, View, Button } from "../../components/Themed";
import { auth } from "../../firebaseConfig";
import ErrorDisplay from "../../components/ErrorDisplay";

export default function Login() {
  const [email, setEmail] = React.useState("halecolin4@gmail.com");
  const [password, setPassword] = React.useState("chatapp");
  const [passwordVisible, setPasswordVisible] = React.useState(true);
  const [error, setError] = React.useState("");
  const [loading, setLoading] = React.useState(false);

  const router = useRouter();

  const onSubmitHandler = async ({ email, password, auth }) =&amp;gt; {
    setError("");
    setLoading(true);
    await signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) =&amp;gt; {
        // set user context here
        router.push("/(tabs)");
      })
      .catch((error) =&amp;gt; {
        setError(error.message);
      });
    setLoading(false);
  };

  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;Email&amp;lt;/Text&amp;gt;
        &amp;lt;TextInput
          value={email}
          placeholder="Email"
          onChangeText={(t) =&amp;gt; setEmail(t)}
        /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;Password&amp;lt;/Text&amp;gt;
        &amp;lt;TextInput
          value={password}
          placeholder="Password"
          onChangeText={(t) =&amp;gt; setPassword(t)}
          secureTextEntry={passwordVisible}
          right={
            &amp;lt;TextInput.Icon
              icon="eye"
              onPress={() =&amp;gt; setPasswordVisible((p) =&amp;gt; !p)}
            /&amp;gt;
          }
        /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Button
          mode="contained"
          onPress={() =&amp;gt; onSubmitHandler({ email, password, auth })}
          disabled={loading}
        &amp;gt;
          {loading ? "Loading..." : "Login"}
        &amp;lt;/Button&amp;gt;
        &amp;lt;ErrorDisplay message={error} /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;TouchableOpacity onPress={() =&amp;gt; router.push("/(auth)/resetPassword")}&amp;gt;
          &amp;lt;Text&amp;gt;Reset password?&amp;lt;/Text&amp;gt;
        &amp;lt;/TouchableOpacity&amp;gt;
      &amp;lt;/View&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
    flex: 1,
    rowGap: 20,
  },
  header: {
    padding: 6,
    borderColor: "#eeeeee60",
    borderBottomWidth: 1,
    width: "100%",
  },
  title: {
    color: "#eee",
    fontSize: 20,
    fontWeight: "bold",
  },
  separator: {
    marginVertical: 30,
    height: 1,
    width: "80%",
  },
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last part of this app is the reset password. What this screen does is send an email to the user which allows them to reset their password through a link there. So all we need to have on that page is their email and firebase authentication will do the rest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Text, View, Button } from "../../components/Themed";
import ErrorDisplay from "../../components/ErrorDisplay";
import { auth } from "../../firebaseConfig";

export default function Login() {
  const [visible, setVisible] = React.useState(false);
  const [email, setEmail] = React.useState("");
  const [error, setError] = React.useState("");
  const [loading, setLoading] = React.useState(false);

  const router = useRouter();

  const onPasswordResetHandler = async ({ auth }) =&amp;gt; {
    setError("");
    setLoading(true);
    await sendPasswordResetEmail(auth, email)
      .then(() =&amp;gt; {
        setVisible(true);
      })
      .catch((error) =&amp;gt; {
        setError(error.message);
      });
    setLoading(false);
  };

  return (
    &amp;lt;View style={styles.container}&amp;gt;
      &amp;lt;View&amp;gt;
        &amp;lt;Text&amp;gt;Email&amp;lt;/Text&amp;gt;
        &amp;lt;TextInput
          value={email}
          placeholder="Email"
          onChangeText={(t) =&amp;gt; setEmail(t)}
        /&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;View style={styles.buttons}&amp;gt;
        &amp;lt;Button
          onPress={() =&amp;gt; router.push("/(auth)")}
          mode="contained"
          style={{ flex: 1 }}
        &amp;gt;
          Back
        &amp;lt;/Button&amp;gt;
        &amp;lt;Button
          mode="contained"
          onPress={() =&amp;gt; onPasswordResetHandler({ auth })}
          style={{ flex: 1 }}
        &amp;gt;
          {loading ? "Loading..." : "Send Reset Link"}
        &amp;lt;/Button&amp;gt;
      &amp;lt;/View&amp;gt;
      &amp;lt;ErrorDisplay message={error} /&amp;gt;
      &amp;lt;Snackbar
        visible={visible}
        onDismiss={() =&amp;gt; setVisible(false)}
        action={{
          label: "Close",
          onPress: () =&amp;gt; setVisible(false),
        }}
      &amp;gt;
        &amp;lt;Text&amp;gt;
          An email link to reset your password has been sent to {email}.
        &amp;lt;/Text&amp;gt;
      &amp;lt;/Snackbar&amp;gt;
    &amp;lt;/View&amp;gt;
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
    flex: 1,
    rowGap: 20,
  },
  buttons: {
    flexDirection: "row",
    columnGap: 12,
    alignItems: "stretch",
  },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last two screen in the tabs directory are just empty screens to show how you can get into the app after you have successfully logged in. If you want to look through the entire project you can find it here on &lt;a href="https://github.com/codingcruxes/Learning-React-Native-Firebase-Authentication" rel="noopener noreferrer"&gt;github&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>reactnative</category>
      <category>firebase</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
