casper's Profile Image

Full Stack Web/Mobile Developer

Dec, 11, 2024

React Native Expo Tutorial #3 | Ecommerce App - Sign In & Sign Up Screens

we created user screen and added to our tab layout and created sign in, sign up, forgot password and otp components.

React Native Expo Tutorial #3 | Ecommerce App - Sign In & Sign Up Screens Image

You can also watch the YouTube video:

React Native Expo Tutorial #3 | Ecommerce App - Sign In & Sign Up Screens

Installing Gluestack UI Components

npx gluestack-ui add form-control input

Let's edit the TabLayout app/(tabs)/_layout.tsx file:

import { Icon } from "@/components/ui/icon";
import { Tabs } from "expo-router";
import { Home, ShoppingCart, User } from "lucide-react-native";

const TabLayout = () => {
  return (
    <Tabs screenOptions={{ tabBarActiveTintColor: "blue" }}>
      <Tabs.Screen
        name="index"
        options={{
          title: "Home",
          tabBarIcon: () => <Icon as={Home} />,
        }}
      />
      <Tabs.Screen
        name="cart"
        options={{
          title: "Cart",
          tabBarIcon: () => <Icon as={ShoppingCart} />,
        }}
      />
      <Tabs.Screen
        name="user"
        options={{
          title: "User",
          tabBarIcon: () => <Icon as={User} />,
        }}
      />
    </Tabs>
  );
};

export default TabLayout;

Creating user.tsx file in app/(tabs) folder

import ForgotPassword from "@/components/ForgotPassword";
import OTP from "@/components/OTP";
import SignIn from "@/components/SignIn";
import SignUp from "@/components/SignUp";
import { Box } from "@/components/ui/box";
import { useState } from "react";

const UserScreen = () => {
  const [currentComponent, setCurrentComponent] = useState("SignIn");

  return (
    <Box className="flex-1 p-8 bg-white">
      {currentComponent === "SignIn" ? (
        <SignIn setCurrentComponent={setCurrentComponent} />
      ) : undefined}
      {currentComponent === "SignUp" ? (
        <SignUp setCurrentComponent={setCurrentComponent} />
      ) : undefined}
      {currentComponent === "ForgotPassword" ? (
        <ForgotPassword setCurrentComponent={setCurrentComponent} />
      ) : undefined}
      {currentComponent === "OTP" ? (
        <OTP setCurrentComponent={setCurrentComponent} />
      ) : undefined}
    </Box>
  );
};

export default UserScreen;

Creating SignIn and SignUp Components

Create SignIn.tsx in components folder:

import { Button, ButtonText } from "@/components/ui/button";
import { FormControl } from "@/components/ui/form-control";
import { Heading } from "@/components/ui/heading";
import { Input, InputField, InputIcon, InputSlot } from "@/components/ui/input";
import { Text } from "@/components/ui/text";
import { VStack } from "@/components/ui/vstack";
import { EyeIcon, EyeOffIcon } from "lucide-react-native";
import { useState } from "react";
import { Box } from "./ui/box";
import { Pressable } from "react-native";

interface ISignIn {
  setCurrentComponent: React.Dispatch<React.SetStateAction<string>>;
}

const SignIn: React.FC<ISignIn> = ({ setCurrentComponent }) => {
  const [showPassword, setShowPassword] = useState(false);

  const handleState = () => {
    setShowPassword((showState) => {
      return !showState;
    });
  };

  return (
    <FormControl className="p-4 border rounded-lg border-outline-300">
      <VStack space="xl">
        <Heading className="text-typography-900 leading-2">Sign In</Heading>
        <VStack space="xs">
          <Text className="text-typography-500 leading-1">Email</Text>
          <Input>
            <InputField type="text" />
          </Input>
        </VStack>
        <VStack space="xs">
          <Text className="text-typography-500 leading-1">Password</Text>
          <Input className="text-center">
            <InputField type={showPassword ? "text" : "password"} />
            <InputSlot className="pr-3" onPress={handleState}>
              {/* EyeIcon, EyeOffIcon are both imported from 'lucide-react-native' */}
              <InputIcon
                as={showPassword ? EyeIcon : EyeOffIcon}
                className="text-blue-500"
              />
            </InputSlot>
          </Input>

          <Box className="flex flex-row items-center justify-between mt-2">
            <Pressable onPress={() => setCurrentComponent("SignUp")}>
              <Text className="text-blue-500">Sign Up</Text>
            </Pressable>

            <Pressable onPress={() => setCurrentComponent("ForgotPassword")}>
              <Text className="text-blue-500">Forgot Password?</Text>
            </Pressable>
          </Box>
        </VStack>

        <Button
          className="bg-blue-500"
          onPress={() => setCurrentComponent("OTP")}
        >
          <ButtonText className="text-typography-0 text-center flex-1">
            Sign In
          </ButtonText>
        </Button>
      </VStack>
    </FormControl>
  );
};

export default SignIn;

Create SignUp.tsx in components folder:

import { Button, ButtonText } from "@/components/ui/button";
import { FormControl } from "@/components/ui/form-control";
import { Heading } from "@/components/ui/heading";
import { Input, InputField, InputIcon, InputSlot } from "@/components/ui/input";
import { Text } from "@/components/ui/text";
import { VStack } from "@/components/ui/vstack";
import { EyeIcon, EyeOffIcon } from "lucide-react-native";
import { useState } from "react";
import { Pressable } from "react-native";

interface ISignUp {
  setCurrentComponent: React.Dispatch<React.SetStateAction<string>>;
}

const SignUp: React.FC<ISignUp> = ({ setCurrentComponent }) => {
  const [showPassword, setShowPassword] = useState(false);

  const handleState = () => {
    setShowPassword((showState) => {
      return !showState;
    });
  };

  return (
    <FormControl className="p-4 border rounded-lg border-outline-300">
      <VStack space="xl">
        <Heading className="text-typography-900 leading-2">Sign Up</Heading>
        <VStack space="xs">
          <Text className="text-typography-500 leading-1">Email</Text>
          <Input>
            <InputField type="text" />
          </Input>
        </VStack>
        <VStack space="xs">
          <Text className="text-typography-500 leading-1">Password</Text>
          <Input className="text-center">
            <InputField type={showPassword ? "text" : "password"} />
            <InputSlot className="pr-3" onPress={handleState}>
              {/* EyeIcon, EyeOffIcon are both imported from 'lucide-react-native' */}
              <InputIcon
                as={showPassword ? EyeIcon : EyeOffIcon}
                className="text-blue-500"
              />
            </InputSlot>
          </Input>

          <Pressable
            className="mt-2"
            onPress={() => setCurrentComponent("SignIn")}
          >
            <Text className="text-blue-500">Sign In</Text>
          </Pressable>
        </VStack>

        <Button
          className="bg-blue-500"
          onPress={() => setCurrentComponent("SignIn")}
        >
          <ButtonText className="text-typography-0 text-center flex-1">
            Sign Up
          </ButtonText>
        </Button>
      </VStack>
    </FormControl>
  );
};

export default SignUp;

Create ForgotPassword.tsx in your components folder:

import { Pressable } from "react-native";
import { Box } from "./ui/box";
import { FormControl } from "./ui/form-control";
import { Heading } from "./ui/heading";
import { Input, InputField, InputSlot } from "./ui/input";
import { Text } from "./ui/text";
import { VStack } from "./ui/vstack";
import { Button, ButtonText } from "./ui/button";

interface IForgotPassword {
  setCurrentComponent: React.Dispatch<React.SetStateAction<string>>;
}

const ForgotPassword: React.FC<IForgotPassword> = ({ setCurrentComponent }) => {
  return (
    <FormControl className="p-4 border rounded-lg border-outline-300">
      <VStack space="xl">
        <Heading className="text-typography-900 leading-2">
          Forgot Password
        </Heading>
        <VStack space="xs">
          <Text className="text-typography-500 leading-1">Email</Text>
          <Input>
            <InputField type="text" />
          </Input>

          <Pressable onPress={() => setCurrentComponent("SignIn")}>
            <Text className="text-blue-500">Sign In</Text>
          </Pressable>
        </VStack>

        <Button
          className="bg-blue-500"
          onPress={() => setCurrentComponent("SignIn")}
        >
          <ButtonText className="text-typography-0 text-center flex-1">
            Send
          </ButtonText>
        </Button>
      </VStack>
    </FormControl>
  );
};

export default ForgotPassword;

Install react native otp entry before we create the otp component.

yarn add react-native-otp-entry

Create OTP.tsx in your components folder:

import { OtpInput } from "react-native-otp-entry";
import { Box } from "./ui/box";
import { Button, ButtonText } from "./ui/button";
import { Heading } from "./ui/heading";
import { VStack } from "./ui/vstack";
import { Link } from "expo-router";

interface IOTP {
  setCurrentComponent: React.Dispatch<React.SetStateAction<string>>;
}

const OTP: React.FC<IOTP> = ({ setCurrentComponent }) => {
  return (
    <Box className="border-outline-300 border rounded-lg">
      <Box className="p-8">
        <Heading>Enter the code we've sent your email address.</Heading>

        <VStack className="mt-4" space="lg">
          <OtpInput
            numberOfDigits={6}
            onTextChange={(text) => console.log(text)}
          />

          <Link href="/" asChild>
            <Button
              className="bg-blue-500"
              onPress={() => setCurrentComponent("SignIn")}
            >
              <ButtonText>Continue</ButtonText>
            </Button>
          </Link>
        </VStack>
      </Box>
    </Box>
  );
};

export default OTP;

That's it for this tutorial, we created user screen and added to our tab layout and created sign in, sign up, forgot password and otp components.

Next tutorial we'll create profile component.

0
0

Comments (0)