<?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: Olorì Àṣàbí</title>
    <description>The latest articles on DEV Community by Olorì Àṣàbí (@oloriasabi).</description>
    <link>https://dev.to/oloriasabi</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%2F883354%2F8edd7752-68f0-456a-84d6-ecad035452f7.jpeg</url>
      <title>DEV Community: Olorì Àṣàbí</title>
      <link>https://dev.to/oloriasabi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oloriasabi"/>
    <language>en</language>
    <item>
      <title>Form, Page Navigation using React-Router-Dom with Ionic-React, TypeScript, React-Hook-Form, React-Redux, and @reduxjs/toolkit!</title>
      <dc:creator>Olorì Àṣàbí</dc:creator>
      <pubDate>Mon, 07 Aug 2023 12:56:43 +0000</pubDate>
      <link>https://dev.to/oloriasabi/form-page-navigation-using-react-router-dom-with-ionic-react-typescript-react-hook-form-react-redux-and-reduxjstoolkit-3ba4</link>
      <guid>https://dev.to/oloriasabi/form-page-navigation-using-react-router-dom-with-ionic-react-typescript-react-hook-form-react-redux-and-reduxjstoolkit-3ba4</guid>
      <description>&lt;p&gt;Welcome to this comprehensive Ionic-React-Native tutorial, where we'll explore key aspects such as file structuring, page navigation using React-Router-Dom, state management with React-Redux and @reduxjs/toolkit, seamless API connections with @reduxjs/toolkit/query/react, and elegant styling using Ionic. Let's dive in!&lt;/p&gt;

&lt;p&gt;To get started, follow these steps to create your application using Create React App and install the necessary dependencies for managing user state with React-Redux and React Router. Before proceeding, ensure you have Node.js installed, a code editor (preferably Visual Studio Code), and a basic understanding of React.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create the React Application
&lt;/h2&gt;

&lt;p&gt;Open your terminal or command prompt and run the following command to create a new React application using Create React App:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g @ionic/cli

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

&lt;/div&gt;



&lt;p&gt;Now, create the Ionic React Native app with TypeScript template using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic start my_ionic_react_native_app blank --type=react --capacitor --language=typescript

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

&lt;/div&gt;



&lt;p&gt;This will generate a new folder named my-app containing the basic structure of your React application.&lt;/p&gt;

&lt;p&gt;This command creates a new Ionic app with a blank template, using React as the framework, TypeScript as the language, and Capacitor for native integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Navigate to the Application Directory
&lt;/h2&gt;

&lt;p&gt;Change your working directory to the newly created application folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd my_ionic_react_native_app

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Run the App
&lt;/h2&gt;

&lt;p&gt;To run the app in a development server, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ionic serve

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

&lt;/div&gt;



&lt;p&gt;This will open the app in your web browser, and you can see the web version of your Ionic React Native app.&lt;/p&gt;

&lt;p&gt;Step 4: Set Up Native Platforms (Optional)&lt;/p&gt;

&lt;p&gt;If you want to build the app for native platforms (iOS and Android), you'll need to set up the native platforms using Capacitor. First, make sure you have Xcode installed for iOS development and Android Studio for Android development.&lt;/p&gt;

&lt;p&gt;To add the native platforms, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx cap add ios
npx cap add android

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Build the Native App
&lt;/h2&gt;

&lt;p&gt;After adding the native platforms, you can build the app for each platform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx cap copy
npx cap open ios   // For iOS
npx cap open android   // For Android

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

&lt;/div&gt;



&lt;p&gt;These commands will open the native projects in Xcode and Android Studio, where you can build, run, and test your app on actual devices or emulators.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Install React-Redux, React Router, @reduxjs/toolkit, and React Hook Form Dependencies
&lt;/h2&gt;

&lt;p&gt;Now that we have our Ionic React Native app set up, let's proceed with installing the necessary dependencies to manage user state, handle API connections, and handle form input with React Hook Form.&lt;/p&gt;

&lt;p&gt;In your terminal or command prompt, run the following command to install the required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-redux react-router-dom @reduxjs/toolkit @reduxjs/toolkit/query/react react-hook-form

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

&lt;/div&gt;



&lt;p&gt;With these dependencies installed, our app is equipped with powerful tools to efficiently manage state, handle API connections with @reduxjs/toolkit/query/react, and seamlessly handle form input using React Hook Form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Organizing File Structure
&lt;/h2&gt;

&lt;p&gt;A well-organized file structure is crucial for a scalable and maintainable project. Let's reorganize our project to keep it clean and organized. Here's a suggested file structure for our Ionic React Native app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_ionic_react_native_app
  |- src
        |- pages
          |- SignUp.tsx
          |- Login.tsx
          |- Home.tsx
          |- ForgotPassword.tsx
          |- ResetPassword.tsx
      |- store
          |- apiSlice.ts
          |- rootReducer.ts
      |- interfaces.ts
      |- Routes.tsx
      |- App.tsx
      |- index.tsx
  |- public
      |- index.html
      |- ...

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

&lt;/div&gt;



&lt;p&gt;In this file structure, we've grouped related components into the components folder, pages into the pages folder, and Redux-related code into the store folder. The interfaces.ts file is used to define types and interfaces for better type safety and code consistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Setting Up React Router with Ionic
&lt;/h2&gt;

&lt;p&gt;In the Routes.tsx file, we'll set up React Router with Ionic to handle navigation between different pages. Replace the content of Routes.tsx with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { IonRouterOutlet } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import { Route, Redirect } from 'react-router-dom';
import SignUp from './pages/SignUp';
import Login from './pages/Login';
import Home from './pages/Home';
import ForgotPassword from './pages/ForgotPassword';
import ResetPassword from './pages/ResetPassword';

const Routes: React.FC = () =&amp;gt; {
  return (
    &amp;lt;IonReactRouter&amp;gt;
      &amp;lt;IonRouterOutlet&amp;gt;
        &amp;lt;Route path="/" component={Home} exact /&amp;gt;
        &amp;lt;Route path="/sign-up" component={SignUp} exact /&amp;gt;
        &amp;lt;Route path="/login" component={Login} exact /&amp;gt;
        &amp;lt;Route path="/forgot-password" component={ForgotPassword} exact /&amp;gt;
        &amp;lt;Route path="/reset-password" component={ResetPassword} exact /&amp;gt;
        {/* Add other routes as needed */}
        &amp;lt;Route exact path="/"&amp;gt;
          &amp;lt;Redirect to="/" /&amp;gt;
        &amp;lt;/Route&amp;gt;
      &amp;lt;/IonRouterOutlet&amp;gt;
    &amp;lt;/IonReactRouter&amp;gt;
  );
};

export default Routes;


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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 9: Setting up the Project and Store
&lt;/h2&gt;

&lt;p&gt;Create a file named interface.ts and add the all necessary interface to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
//interface.ts

export interface User {
  id: number;
  username: string;
  email: string;
  // Add more user properties as needed
}

export interface UserState {
  user: User | null;
  isLoading: boolean;
  error: string | null;
}

export interface RootState {
  user: UserState;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the store folder, create a file named userSlice.ts with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { User, RootState, UserState } from './interface';

const initialState: UserState = {
  user: null,
  isLoading: false,
  error: null,
};

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    setUser: (state, action: PayloadAction&amp;lt;User&amp;gt;) =&amp;gt; {
      state.user = action.payload;
      state.isLoading = false;
      state.error = null;
    },
    setLoading: (state, action: PayloadAction&amp;lt;boolean&amp;gt;) =&amp;gt; {
      state.isLoading = action.payload;
    },
    setError: (state, action: PayloadAction&amp;lt;string&amp;gt;) =&amp;gt; {
      state.isLoading = false;
      state.error = action.payload;
    },
  },
});

// Export actions
export const { setUser, setLoading, setError } = userSlice.actions;

// Selector to get the user from the state
export const selectUser = (state: RootState) =&amp;gt; state.user.user;

// Selector to get the loading state
export const selectLoading = (state: RootState) =&amp;gt; state.user.isLoading;

// Selector to get the error
export const selectError = (state: RootState) =&amp;gt; state.user.error;

export default userSlice.reducer;

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

&lt;/div&gt;



&lt;p&gt;In the src folder, create a new folder named store to house our Redux-related code. In your rootReducer.ts file (in the same store folder), import and add the userSlice reducer to the root reducer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { combineReducers } from '@reduxjs/toolkit';
import userReducer from './userSlice'; // Import your userSlice reducer here

const rootReducer = combineReducers({
  // Other reducers go here
  user: userReducer,
});

export type RootState = ReturnType&amp;lt;typeof rootReducer&amp;gt;;
export default rootReducer;

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

&lt;/div&gt;



&lt;p&gt;Next, create a file named apiSlice.ts in the store folder. This file will handle API connections using @reduxjs/toolkit/query/react. Here's a basic example of how it can be structured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

// Define your API endpoints and base query
const api = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: 'https://api.example.com/' }), // Replace with your API base URL
  endpoints: (builder) =&amp;gt; ({
    // Define your API endpoints here
    // For example:
    // getUserById: builder.query&amp;lt;User, number&amp;gt;({
    //   query: (id) =&amp;gt; `user/${id}`,
    // }),
  }),
});

// Export the hooks for using the API endpoints
// For example:
// export const { useGetUserByIdQuery } = api;

// Export the API object to use in the store
export default api;

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

&lt;/div&gt;



&lt;p&gt;Inside the store folder (same location where userSlice.ts and rootReducer.ts are located), create a file named store.ts with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './rootReducer'; // Import your root reducer here

const store = configureStore({
  reducer: rootReducer,
  // Add middleware or other store configurations as needed
});

export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType&amp;lt;typeof rootReducer&amp;gt;;

export default store;

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

&lt;/div&gt;



&lt;p&gt;Now, let's set up the Redux store in App.tsx. Import the necessary dependencies and the rootReducer from the store folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { Provider } from 'react-redux';
import Routes from './Routes';
import store from './store/store'; 

const App: React.FC = () =&amp;gt; {
  return (
    &amp;lt;Provider store={store}&amp;gt;
      &amp;lt;Routes /&amp;gt;
    &amp;lt;/Provider&amp;gt;
  );
};

export default App;

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

&lt;/div&gt;



&lt;p&gt;With these changes, you've now properly set up the project structure and the Redux store using @reduxjs/toolkit/query/react for API connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10: Using React Hook Form for Form Handling with Ionic React
&lt;/h2&gt;

&lt;p&gt;Create a file named interface.ts and add the all necessary interface to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// interface.ts
export interface SignUpForm {
  username: string;
  email: string;
  password: string;
  confirmPassword: string;
}

export interface LoginForm {
  email: string;
  password: string;
}

export interface ForgotPasswordForm {
  email: string;
}

export interface ResetPasswordForm {
  newPassword: string;
  confirmPassword: string;
}

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

&lt;/div&gt;



&lt;p&gt;Component Organization: Create a PasswordField component to handle password input with show/hide password functionality:&lt;br&gt;
SignUp.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Create PasswordField.tsx
import React, { useState } from 'react';
import { IonInput, IonIcon } from '@ionic/react';
import { eye, eyeOff } from 'ionicons/icons';

interface PasswordFieldProps {
  label: string;
  field: any;
  fieldState: any;
  register: (name: string) =&amp;gt; void;
}

const PasswordField: React.FC&amp;lt;PasswordFieldProps&amp;gt; = ({ label, field, fieldState, register }) =&amp;gt; {
  const [visibility, setVisibility] = useState&amp;lt;"text" | "password"&amp;gt;("password");

  const toggleVisibility = () =&amp;gt; {
    setVisibility((prevVisibility) =&amp;gt; (prevVisibility === "password" ? "text" : "password"));
  };

  return (
    &amp;lt;div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', gap: '20px' }}&amp;gt;
      &amp;lt;IonInput
        {...field}
        type={visibility}
        onPaste={(e) =&amp;gt; {
          e.preventDefault();
          return false;
        }}
        required={true}
        onIonChange={(e) =&amp;gt; field.onChange(e.detail.value)}
        onKeyUp={() =&amp;gt; {
          register(field.name);
        }}
        style={{
          color: '#345430',
          fontSize: '10px',
          borderRadius: '10px',
          border: '2px solid',
          borderColor: fieldState.invalid ? 'red' : '#345430',
          height: '50px',
        }}
      /&amp;gt;
      &amp;lt;IonIcon
        icon={visibility === 'text' ? eye : eyeOff}
        onClick={toggleVisibility}
        style={{ color: '#345430' }}
      /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default PasswordField;

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

&lt;/div&gt;



&lt;p&gt;**Use the PasswordField component in your SignUp component and apply the other suggestions to your code as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { IonContent, IonButton, IonLabel, IonItem, IonPage, IonInput } from '@ionic/react';
import { useForm, Controller } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { setUser, selectLoading } from './store/userSlice';
import { SignUpForm } from './interface';
import PasswordField from '../components/PasswordField'; // Import the PasswordField component

const SignUp: React.FC = () =&amp;gt; {
  const dispatch = useDispatch();
  const isLoading = useSelector(selectLoading);

 const { control, handleSubmit, getValues, setError: setErrorFromForm, watch, formState: { errors, isValid }, register, trigger } = useForm&amp;lt;SignUpForm&amp;gt;({
    defaultValues: {
      email: '',
      username: '',
      password: '',
      confirmPassword: '',
    },
  });

  const onSubmit = (data: SignUpForm) =&amp;gt; {
    // Handle sign up form submission
    console.log(data);

    // Example: Dispatch setUser action to update user data in the state
    dispatch(setUser(data));
  };

  const handleConfirmPassword = () =&amp;gt; {
    const { password, confirmPassword } = getValues();
    if (password !== confirmPassword) {
      setErrorFromForm('confirmPassword', { type: 'manual', message: 'Passwords do not match' });
    }
  };

  const confirmPassword = watch('confirmPassword');

return (
    &amp;lt;IonPage&amp;gt;
      &amp;lt;IonContent&amp;gt;
        &amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
          &amp;lt;IonItem&amp;gt;
            &amp;lt;IonLabel position="floating"&amp;gt;Username&amp;lt;/IonLabel&amp;gt;
            &amp;lt;Controller
              render={({ field, fieldState }) =&amp;gt; (
                &amp;lt;IonInput
                  {...field}
                  {...register("username")}
                  placeholder="Enter Username"
                  aria-label="Username"
                  onIonChange={(e) =&amp;gt; field.onChange(e.detail.value)}
                  required={true}
                  onKeyUp={() =&amp;gt; {
                    trigger('username');
                  }}

                  style={{
                    color: '#345430',
                    fontSize: '10px',
                    borderRadius: '10px',
                    border: '2px solid',
                    borderColor: fieldState.invalid ? 'red' : '#345430',
                    height: '50px',
                  }}
                /&amp;gt;
              )}
              name="username"
              control={control}
              rules={{
                required: 'Username is required',
               pattern: {
                value: /^[A-Za-z0-9_!@#$%^&amp;amp;*()-]+$/,
                message: "Username must contain only letters, numbers, underscores, and symbols !@#$%^&amp;amp;*()-",
              },
            minLength: {
              value: 4,
              message: "Username must be at least 4 characters",
            },
            maxLength: {
              value: 20,
              message: "Username must be less than 20 characters",
            }
              }}
            /&amp;gt;
          &amp;lt;/IonItem&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.username?.message}&amp;lt;/span&amp;gt;
          &amp;lt;IonItem&amp;gt;
            &amp;lt;IonLabel position="floating"&amp;gt;Email&amp;lt;/IonLabel&amp;gt;
            &amp;lt;Controller
              render={({ field, fieldState }) =&amp;gt; 
            &amp;lt;IonInput 
            {...field}
            {...register("email")}
            onIonChange={(e) =&amp;gt; field.onChange(e.detail.value)}
                    placeholder="Enter Email" 
                    aria-label="Email"
                required={true}
                    onKeyUp={() =&amp;gt; {
                        trigger("email")
                    }}
                            style={{
                                color: "#345430",
                                fontSize: "10px",
                                borderRadius: "10px",
                                border: "2px solid",
                                borderColor: fieldState.invalid ? "red" : "#345430",
                                height: "50px",
                            }}

            /&amp;gt;}
              name="email"
              control={control}
              rules={{ 
                required: 'Email is required',
                pattern: {
                        value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                        message: "Invalid email address",
             } }}
            /&amp;gt;
          &amp;lt;/IonItem&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.email?.message}&amp;lt;/span&amp;gt;
          &amp;lt;IonItem&amp;gt;
            &amp;lt;IonLabel position="floating"&amp;gt;Password&amp;lt;/IonLabel&amp;gt;
            &amp;lt;Controller
              render={({ field, fieldState }) =&amp;gt; 
            &amp;lt;div 
              style={{
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                width: "100%",
                gap: "20px",
              }}&amp;gt;
    &amp;lt;PasswordField
            label="Password"
            field={field.password}
            fieldState={fieldState.password}
            register={{...register("password")}}
          /&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.password?.message}&amp;lt;/span&amp;gt;
              &amp;lt;/div&amp;gt;
                }
              name="password"
              control={control}
                  rules={{
                required: "Password is required",
                pattern: {
                    value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[.!@#$%^&amp;amp;*])[A-Za-z\d.!@#$%^&amp;amp;*]{8,20}$/,
                    message: "Password must have a capital letter, a small letter, a number, and a symbol (e.g., .!@#$%^&amp;amp;*)",
                  },
                minLength: {
                  value: 8,
                  message: "Password must be at least 8 characters",
                },
                maxLength: {
                  value: 20,
                  message: "Password must be less than 20 characters",
                },
              }}            /&amp;gt;
          &amp;lt;/IonItem&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.password?.message}&amp;lt;/span&amp;gt;
   &amp;lt;IonItem&amp;gt;
            &amp;lt;IonLabel position="floating"&amp;gt;Confirm Password&amp;lt;/IonLabel&amp;gt;
            &amp;lt;Controller
              render={({ field, fieldState }) =&amp;gt;
  &amp;lt;div 
              style={{
                display: "flex",
                justifyContent: "space-between",
                alignItems: "center",
                width: "100%",
                gap: "20px",
              }}&amp;gt;
            &amp;lt;PasswordField
            label="confirmPassword"
            field={field.confirmPassword}
            fieldState={fieldState.confirmPassword}
            register={{...register("confirmPassword")}}
          /&amp;gt;
              &amp;lt;/div&amp;gt;}
              name="confirmPassword"
              control={control}
              rules={{ required: 'Confirm Password is required' }}
            /&amp;gt;
          &amp;lt;/IonItem&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.confirmPassword?.message}&amp;lt;/span&amp;gt;

          &amp;lt;IonButton type="submit" disabled={!isValid || isLoading}&amp;gt;
            {isLoading ? 'Signing Up...' : 'Sign Up'}
          &amp;lt;/IonButton&amp;gt;
          {errors &amp;amp;&amp;amp; &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors}&amp;lt;/span&amp;gt;}
        &amp;lt;/form&amp;gt;
      &amp;lt;/IonContent&amp;gt;
    &amp;lt;/IonPage&amp;gt;
  );
};

export default SignUp;


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

&lt;/div&gt;



&lt;p&gt;Login.tsx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { IonContent, IonButton, IonLabel, IonItem, IonPage, IonInput } from '@ionic/react';
import { useForm, Controller } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { setUser, selectLoading } from './store/userSlice';
import { LoginForm } from './interface';
import PasswordField from '../components/PasswordField';

const LoginPage = () =&amp;gt; {
    const dispatch = useDispatch();
    const isLoading = useSelector(selectLoading);


const { control, handleSubmit,  formState: { errors, isValid }, register, trigger } = useForm&amp;lt;LoginForm&amp;gt;({
    defaultValues: {
      email: "",
      password: "",
    },
  });


const onSubmit = (data: LoginForm) =&amp;gt; {
  // Handle login form submission
  dispatch(setUser(data));
};
  return (
 &amp;lt;IonPage&amp;gt;
    &amp;lt;IonContent&amp;gt;
    &amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
        &amp;lt;IonItem&amp;gt;
        &amp;lt;IonLabel position="floating"&amp;gt;Email&amp;lt;/IonLabel&amp;gt;
        &amp;lt;Controller
             name="email"
             control={control}
             rules={{
               required: 'Email is required',
              pattern: {
             value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
             message: "Invalid email address",
              }
              }}
              render={({ field, fieldState }) =&amp;gt; (
                &amp;lt;IonInput
                  {...field}
                  placeholder="Enter Email"
                  aria-label="Email"
                  onIonChange={(e) =&amp;gt; field.onChange(e.detail.value)}
                  required={true}
                  onKeyUp={() =&amp;gt; {
                    trigger('email');
                  }}
                  {...register("email")}
                  style={{
                    color: '#345430',
                    fontSize: '10px',
                    borderRadius: '10px',
                    border: '2px solid',
                    borderColor: fieldState.invalid ? 'red' : '#345430',
                    height: '50px',
                  }}
                /&amp;gt;
              )}
              /&amp;gt;
             &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.email?.message}&amp;lt;/span&amp;gt;
        &amp;lt;/IonItem&amp;gt;
        &amp;lt;IonItem&amp;gt;
        &amp;lt;IonLabel position="floating"&amp;gt;Password&amp;lt;/IonLabel&amp;gt;
        &amp;lt;Controller
    render={({ field, fieldState }) =&amp;gt; (
      &amp;lt;PasswordField
        label="Password"
        field={field.password}
        fieldState={fieldState.password}
        register={{...register("password")}}
      /&amp;gt;
    )}
    name="password"
    control={control}
    rules={{
      required: "Password is required",
      pattern: {
        value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[.!@#$%^&amp;amp;*])[A-Za-z\d.!@#$%^&amp;amp;*]{8,20}$/,
        message: "Password must have a capital letter, a small letter, a number, and a symbol (e.g., .!@#$%^&amp;amp;*)",
      },
      minLength: {
        value: 8,
        message: "Password must be at least 8 characters",
      },
      maxLength: {
        value: 20,
        message: "Password must be less than 20 characters",
      },
    }}
  /&amp;gt;
            &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.password?.message}&amp;lt;/span&amp;gt;
        &amp;lt;/IonItem&amp;gt;
        &amp;lt;IonButton type="submit" disabled={!isValid || isLoading}&amp;gt;
            {isLoading ? 'Logging In...' : 'Login'}
          &amp;lt;/IonButton&amp;gt;
          {errors &amp;amp;&amp;amp; &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors}&amp;lt;/span&amp;gt;}
        &amp;lt;/form&amp;gt;
    &amp;lt;/IonContent&amp;gt;
 &amp;lt;/IonPage&amp;gt;
  )
}

export default LoginPage

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

&lt;/div&gt;



&lt;p&gt;ResetPassword.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { IonContent, IonButton, IonLabel, IonItem, IonPage,  IonInput } from '@ionic/react';
import { useForm, Controller } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { setUser, selectLoading } from './store/userSlice';
import { ResetPasswordForm } from './interface';
import PasswordField from '../components/PasswordField';

const ResetPassword: React.FC = () =&amp;gt; {
  const dispatch = useDispatch();
  const isLoading = useSelector(selectLoading);

  const { control, handleSubmit, getValues, setError: setErrorFromForm, formState: { errors, isValid },  register, trigger } = useForm&amp;lt;ResetPasswordForm&amp;gt;({
    defaultValues: {
      newPassword: "",
      confirmPassword: "",
    },
  });


  const onSubmit = (data: ResetPasswordForm) =&amp;gt; {
    // Handle reset password form submission
    dispatch(setUser(data));
  };

  const handleConfirmPassword = () =&amp;gt; {
    const { newPassword, confirmPassword } = getValues();
    if (newPassword !== confirmPassword) {
      setErrorFromForm('confirmPassword', { type: 'manual', message: 'Passwords do not match' });
    }
  };

  return (
    &amp;lt;IonPage&amp;gt;
      &amp;lt;IonContent&amp;gt;
        &amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
          {/* New Password Field */}
          &amp;lt;IonItem&amp;gt;
            &amp;lt;IonLabel position="floating"&amp;gt;New Password&amp;lt;/IonLabel&amp;gt;
            &amp;lt;Controller
              render={({ field, fieldState }) =&amp;gt; (
                &amp;lt;PasswordField
                  label="New Password"
                  field={field.newPassword}
                  fieldState={fieldState.newPassword}
                  register={{...register("password")}}
                /&amp;gt;
              )}
              name="newPassword"
              control={control}
              rules={{
                required: "New Password is required",
                pattern: {
                    value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[.!@#$%^&amp;amp;*])[A-Za-z\d.!@#$%^&amp;amp;*]{8,20}$/,
                    message: "Password must have a capital letter, a small letter, a number, and a symbol (e.g., .!@#$%^&amp;amp;*)",
                  },
                  minLength: {
                    value: 8,
                    message: "Password must be at least 8 characters",
                  },
                  maxLength: {
                    value: 20,
                    message: "Password must be less than 20 characters",
                  },
              }}
            /&amp;gt;
          &amp;lt;/IonItem&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.newPassword?.message}&amp;lt;/span&amp;gt;

          {/* Confirm Password Field */}
          &amp;lt;IonItem&amp;gt;
            &amp;lt;IonLabel position="floating"&amp;gt;Confirm Password&amp;lt;/IonLabel&amp;gt;
            &amp;lt;Controller
              render={({ field, fieldState }) =&amp;gt; (
                &amp;lt;PasswordField
                  label="Confirm Password"
                  field={field.confirmPassword}
                  fieldState={fieldState.confirmPassword}
                  register={{...register("confirmPassword")}}
                  onKeyUp={handleConfirmPassword}
                /&amp;gt;
              )}
              name="confirmPassword"
              control={control}
              rules={{ required: 'Confirm Password is required' }}
            /&amp;gt;
          &amp;lt;/IonItem&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.confirmPassword?.message}&amp;lt;/span&amp;gt;

          &amp;lt;IonButton type="submit" disabled={!isValid || isLoading}&amp;gt;
            {isLoading ? 'Submitting...' : 'Submit'}
          &amp;lt;/IonButton&amp;gt;
          {errors &amp;amp;&amp;amp; &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors}&amp;lt;/span&amp;gt;}
        &amp;lt;/form&amp;gt;
      &amp;lt;/IonContent&amp;gt;
    &amp;lt;/IonPage&amp;gt;
  );
};

export default ResetPassword;

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

&lt;/div&gt;



&lt;p&gt;ForgotPassword.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { IonContent, IonButton, IonLabel, IonItem, IonPage, IonInput } from '@ionic/react';
import { useForm, Controller } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { setUser,  selectLoading } from './store/userSlice';
import { ForgotPasswordForm } from './interface';
import PasswordField from '../components/PasswordField';

const ForgotPassword: React.FC = () =&amp;gt; {
  const dispatch = useDispatch();
  const isLoading = useSelector(selectLoading);

  const { control, handleSubmit,  formState: { errors, isValid }, register, trigger } = useForm&amp;lt;ForgotPasswordForm&amp;gt;({
    defaultValues: {
      email: "",
    },
  });

  const onSubmit = (data: ForgotPasswordForm) =&amp;gt; {
    // Handle forgot password form submission
    dispatch(setUser(data));
  };

  return (
    &amp;lt;IonPage&amp;gt;
      &amp;lt;IonContent&amp;gt;
        &amp;lt;form onSubmit={handleSubmit(onSubmit)}&amp;gt;
          {/* Email Field */}
          &amp;lt;IonItem&amp;gt;
            &amp;lt;IonLabel position="floating"&amp;gt;Email&amp;lt;/IonLabel&amp;gt;
            &amp;lt;Controller
              name="email"
              control={control}
              rules={{
                required: 'Email is required',
                pattern: {
                  value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                  message: "Invalid email address",
                },
              }}
              render={({ field, fieldState }) =&amp;gt; (
                &amp;lt;IonInput
                  {...field}
                  {...register("password")}
                  placeholder="Enter Email"
                  aria-label="Email"
                  onIonChange={(e) =&amp;gt; field.onChange(e.detail.value)}
                  required={true}
                  onKeyUp={() =&amp;gt; {
                    trigger('email');
                  }}
                  style={{
                    color: '#345430',
                    fontSize: '10px',
                    borderRadius: '10px',
                    border: '2px solid',
                    borderColor: fieldState.invalid ? 'red' : '#345430',
                    height: '50px',
                  }}
                /&amp;gt;
              )}
            /&amp;gt;
          &amp;lt;/IonItem&amp;gt;
          &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors.email?.message}&amp;lt;/span&amp;gt;

          &amp;lt;IonButton type="submit"  disabled={!isValid || isLoading}&amp;gt;
            {isLoading ? 'Submitting...' : 'Submit'}
          &amp;lt;/IonButton&amp;gt;
          {errors &amp;amp;&amp;amp; &amp;lt;span style={{ color: 'red' }}&amp;gt;{errors}&amp;lt;/span&amp;gt;}
        &amp;lt;/form&amp;gt;
      &amp;lt;/IonContent&amp;gt;
    &amp;lt;/IonPage&amp;gt;
  );
};

export default ForgotPassword;

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

&lt;/div&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%2F38b7uyykpft8k9s2txri.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%2F38b7uyykpft8k9s2txri.png" alt="Image description"&gt;&lt;/a&gt;&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%2Fm7233v1ruh5s0moy7ymm.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%2Fm7233v1ruh5s0moy7ymm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we covered the essentials of creating forms, debugging, and page navigation in an Ionic-React-Native application. We harnessed tools like TypeScript, React Hook Form, React-Redux, and @reduxjs/toolkit to build a powerful app.&lt;/p&gt;

&lt;p&gt;We started by mastering form creation with React Hook Form, ensuring accurate user input through validation. Then, we explored debugging techniques, fine-tuning our app for a smooth user experience.&lt;/p&gt;

&lt;p&gt;Our journey continued with React-Router-Dom and Ionic, where we learned to seamlessly navigate between app sections, enhancing user engagement.&lt;/p&gt;

&lt;p&gt;We leveraged Redux and @reduxjs/toolkit to manage state efficiently, establishing a solid architecture for communication between components.&lt;/p&gt;

&lt;p&gt;By completing this tutorial, you've gained a strong foundation for crafting advanced Ionic-React-Native apps. Good luck applying these skills to your future projects!&lt;/p&gt;

&lt;p&gt;Feel free to contact me for jobs and project opportunities &lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>redux</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to create table with data grid, checkbox and pagination using React table and Tailwind CSS.</title>
      <dc:creator>Olorì Àṣàbí</dc:creator>
      <pubDate>Thu, 08 Sep 2022 21:34:21 +0000</pubDate>
      <link>https://dev.to/oloriasabi/how-to-create-table-with-data-grid-checkbox-and-pagination-using-react-table-and-tailwind-css-33c</link>
      <guid>https://dev.to/oloriasabi/how-to-create-table-with-data-grid-checkbox-and-pagination-using-react-table-and-tailwind-css-33c</guid>
      <description>&lt;p&gt;In this tutorial, we will be learning how to build a smart React data table UI with many functionalities such as  searching, row and column selection, customised pagination using numbers using &lt;a href="https://www.npmjs.com/package/react-table" rel="noopener noreferrer"&gt;react-table&lt;/a&gt; and styling with Tailwind CSS.&lt;/p&gt;

&lt;p&gt;Make sure you have the necessary requirements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js installed&lt;/li&gt;
&lt;li&gt;Code editor ( Visual Studio Code preferably )&lt;/li&gt;
&lt;li&gt;Basic knowledge of React&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  React Table
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tanstack.com/table/v8/docs/guide/introduction" rel="noopener noreferrer"&gt;React-Table&lt;/a&gt; UI library is very lightweight and offers all the basic features necessary for displaying data on any simple table. For most developers, when building a dashboard displaying data in form of a table with columns is usually necessary and required, react-table provides features like search, filters, and sorting, pagination and many more.&lt;/p&gt;

&lt;p&gt;First, let’s get started by creating our application using Create React App and installing all necessary dependencies by running the following commands:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx create-react-app react-table-dashboard
cd react-table-dashboard
npm instal react-table 


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

&lt;/div&gt;

&lt;p&gt;Setting Up Our project by a data folder with a dummy.js to provide the necessary data to display on our table.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

export const customersData = () =&amp;gt; {
  const data = [
  {
    customerID: 1001,
    customer: 'Nirav Joshi',
    CustomerEmail: 'nirav@gmail.com',
    imgUrl:
      avatar2,
    deposit: 'NGN 34,600',
    date: 'Jan 6, 2022 09:21',
    voucherNo: '00437E',
    status: 'Successful',
    selected: false,
    customerNumber: "+234 803 0000",
  },
  {
    CustomerID: 1002,
    customer: 'Sunil Joshi',
    deposit: 'NGN 34,600',
    date: 'Jan 6, 2022 09:21',
    voucherNo: '00437E',
    status: 'Successful',
    CustomerEmail: 'sunil@gmail.com',
    Status: 'Active',
    imgUrl:
      avatar3,
          customerNumber: "+234 803 0000",
      selected: false,
  },
  {
    CustomerID: 1003,
    customer:'Andrew McDownland',
    deposit: 'NGN 34,600',
    date: 'Jan 6, 2022 09:21',
    voucherNo: '00437E',
    status: 'Failed',
    CustomerEmail: 'andrew@gmail.com',
    imgUrl:
      avatar4,
      customerNumber: "+234 803 0000",
  },
  {
    CustomerID: 1004,
    customer:'Christopher Jamil',
    deposit: 'NGN 34,600',
    date: 'Jan 6, 2022 09:21',
    voucherNo: '00437E',
    status: 'Successful',
    CustomerEmail: 'jamil@gmail.com',
    imgUrl:
      avatar,
          customerNumber: "+234 803 0000",
  },
  {
    CustomerID: 1005,
    customer:'Andrew McDownland',
    deposit: 'NGN 34,600',
    date: 'Jan 6, 2022 09:21',
    voucherNo: '00437E',
    status: 'Successful',
    CustomerName: 'Michael',
    customerEmail: 'michael@gmail.com',
   imgUrl:
      avatar2,
        customerNumber: "+234 803 0000",
  },
 {
    CustomerID: 1005,
    customer:'Andrew McDownland',
    deposit: 'NGN 34,600',
    date: 'Jan 6, 2022 09:21',
    voucherNo: '00437E',
    status: 'Successful',
    CustomerName: 'Michael',
    customerEmail: 'michael@gmail.com',
    imgUrl:
      avatar2,
        customerNumber: "+234 803 0000",
  }

];
 return [data]
}


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

&lt;/div&gt;

&lt;p&gt;And creating a file in src/Table.js, we'll mostly use the code of the basic example from the React Table &lt;a href="https://tanstack.com/table/v8/docs/examples/react/basic?from=reactTableV7&amp;amp;original=https://react-table-v7.tanstack.com/docs/examples/basic" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s create the basic UI with the useTable Hook. We will create a new Table component that will accept two props: data and columns. data is the data we got through the dummy data we created, and columns is the object to define the table columns (headers, rows, how the row will be shown, etc.).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import React, {useMemo} from 'react';
import { customersData } from '../data/dummy';

function Table() {
     const columns = useMemo(() =&amp;gt; [
      {
        Header: "Customer",
        accessor: "customer",
      },
      {
        Header: "Deposit",
        accessor: "deposit",
      },
      {
        Header: "Date",
        accessor: "date",
      },
      {
        Header: "Voucher NO.",
        accessor: "voucherNo",
      },
      {
        Header: "Trans.Status",
        accessor: "status",
      },

], []);

  const data = useMemo(() =&amp;gt; customersData(), []);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Hello React!&amp;lt;/h1&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;Table columns={columns} data={data} /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default Table;


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

&lt;/div&gt;

&lt;p&gt;run &lt;code&gt;npm start&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Our Table
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-table" rel="noopener noreferrer"&gt;React-table&lt;/a&gt; uses React Hook called useTable. The Hook will return the necessary props for the table, body, and transformed data to create the header and cells. The header will be created by iterating through headerGroups, and the rows for the table body will be created by looping through rows. We'll also set up Tailwind CSS in our project, follow the instructions from the &lt;a href="https://tailwindcss.com/docs/guides/create-react-app" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;. It's a few steps, but it should work seamlessly, we'll also copy most of the classes from the table component on &lt;a href="https://tailwindui.com/components/application-ui/lists/tables" rel="noopener noreferrer"&gt;TailwindUI&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { useTable } from "react-table";

function Table({ columns, data }) {
  // Use the state and functions returned from useTable to build your UI
  const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
    useTable({
      columns,
      data,
    });

  // Render the UI for your table and the styles
  return (
  &amp;lt;div className="mt-2 flex flex-col"&amp;gt;
            &amp;lt;div className="-my-2 overflow-x-auto -mx-4 sm:-mx-6 lg:-mx-8"&amp;gt;
              &amp;lt;div  className="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8"&amp;gt;
                &amp;lt;div className="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg"&amp;gt;
                    &amp;lt;table {...getTableProps()} className="min-w-full divide-y divide-gray-200"&amp;gt;
                      &amp;lt;thead className="bg-gray-10"&amp;gt;
                      {headerGroups.map((headerGroup) =&amp;gt; (
                          &amp;lt;tr {...headerGroup.getHeaderGroupProps()}&amp;gt;
                              {headerGroup.headers.map((column) =&amp;gt; (
                                  &amp;lt;th {...column.getHeaderProps()}
                                  className="px-6 py-5 text-left text-20 font-medium text-gray-400 uppercase rounded-sm tracking-wider"
                                  &amp;gt;
                                    {column.render("Header")}
                                    &amp;lt;/th&amp;gt;
                              ))}
                          &amp;lt;/tr&amp;gt;
                      ))}
                  &amp;lt;/thead&amp;gt;
                  &amp;lt;tbody {...getTableBodyProps()}
                  className="bg-white divide-y divide-gray-200"&amp;gt;
                    {row.map((row, i) =&amp;gt; {
                      prepareRow(row);
                      return (
                          &amp;lt;tr {...row.getRowProps()}&amp;gt;
                          {row.cells.map((cell) =&amp;gt; {
                              return &amp;lt;td {...cell.getCellProps()} className="px-6 py-10 whitespace-nowrap"&amp;gt;{cell.render("Cell")}&amp;lt;/td&amp;gt;
                          })}
                          &amp;lt;/tr&amp;gt;
                      );
                      })}
                  &amp;lt;/tbody&amp;gt;
                    &amp;lt;/table&amp;gt;
                &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
         &amp;lt;/div&amp;gt;
  );
}

export default Table;


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

&lt;/div&gt;

&lt;p&gt;Run &lt;code&gt;npm start&lt;/code&gt; to open the app in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Search Functionality with GlobalFilter
&lt;/h2&gt;

&lt;p&gt;Let's add a global search feature to our table, it can enable users to find text typed in the input field, and the table only displays rows with data that matches this text.&lt;/p&gt;

&lt;p&gt;In the src/Table.js, add the following code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { useTable, useGlobalFilter, useAsyncDebounce } from 'react-table'  // new

// Define a UI for filtering

function GlobalFilter({
    globalFilter,
    setGlobalFilter,
    placeholder
  }) {
    const [value, setValue] = useState(globalFilter)
    const onChange = useAsyncDebounce(value =&amp;gt; {
      setGlobalFilter(value || undefined)
    }, 200)

    return (
      &amp;lt;span className='flex justify-between  pt-10 pb-10 '&amp;gt;
        &amp;lt;input
          value={value || ""}
          onChange={e =&amp;gt; {
            setValue(e.target.value);
            onChange(e.target.value);
          }}
          className='w-8/12 rounded-xl border p-4 text-gray-500 cursor-pointer' 
          type="search"  
          placeholder="Search..."
        /&amp;gt;
      &amp;lt;/span&amp;gt;
    )
  };  


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

&lt;/div&gt;

&lt;p&gt;The GlobalFilter component accepts a few props that will be provided by the Table component.&lt;/p&gt;

&lt;p&gt;It also defines value using the useState hook, which is coupled to the  element's value. When the user types in the  element, the onChange handler will call the setGlobalFilter method to pass the value to the parent Table component. The useAsyncDebounce is used to add a little delay to avoid too many re-renders while the user is typing.&lt;/p&gt;

&lt;p&gt;Finally, make a few updates to the Table component to integrate the GlobalFilter.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

function Table({ columns, data }) {
  // Use the state and functions returned from useTable 
  const {
    ...
    state, // new
    preGlobalFilteredRows, // new
    setGlobalFilter, // new
  } = useTable({
    columns,
    data,
  },
    useGlobalFilter // new
  )

  // Render the UI for your table
  return (
    &amp;lt;&amp;gt;
      &amp;lt;GlobalFilter
        preGlobalFilteredRows={preGlobalFilteredRows}
        globalFilter={state.globalFilter}
        setGlobalFilter={setGlobalFilter}
      /&amp;gt;
      &amp;lt;table {...getTableProps()}&amp;gt;
        ...
      &amp;lt;/table&amp;gt;
    &amp;lt;/&amp;gt;
  )
}


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

&lt;/div&gt;

&lt;p&gt;run &lt;code&gt;npm start&lt;/code&gt; and try out the search functionality in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding useRowSelectColumn
&lt;/h2&gt;

&lt;p&gt;The useRowSelectColumn react-table plugin hook injects a new column at the beginning showing checkboxes to select rows. This hook depends on the useRowSelect hook from react-table.&lt;/p&gt;

&lt;p&gt;First we need to add this dependency &lt;a href="https://lineup-lite.js.org/docs/hooks/userowselectcolumn/" rel="noopener noreferrer"&gt;@lineup-lite/hooks&lt;/a&gt; to help with row and column selection in the table. Enter the following command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @lineup-lite/hooks&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;In the src/Table.js, add the following code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { useTable, useGlobalFilter, useAsyncDebounce, useRowSelect } from 'react-table';
import { useRowSelectColumn } from '@lineup-lite/hooks';


  // Use the state and functions returned from useTable to build your UI
    const {
    ...
   getTableProps,
   getTableBodyProps, 
   headerGroups, 
   rows, 
   prepareRow
  } = useTable({
    columns,
    data,
  },
    useRowSelect, //new
    useRowSelectColumn //new
  );

  // Render the UI for your table
  return (
    &amp;lt;table {...getTableProps()}&amp;gt;
      &amp;lt;thead&amp;gt;
        {headerGroups.map((headerGroup) =&amp;gt; (
          &amp;lt;tr {...headerGroup.getHeaderGroupProps()}&amp;gt;
            {headerGroup.headers.map((column) =&amp;gt; (
              &amp;lt;th {...column.getHeaderProps()}&amp;gt;
                {column.render('Header')}
                {column.id === 'selection' &amp;amp;&amp;amp; column.render('Summary')}
              &amp;lt;/th&amp;gt;
            ))}
          &amp;lt;/tr&amp;gt;
        ))}
      &amp;lt;/thead&amp;gt;
      &amp;lt;tbody {...getTableBodyProps()}&amp;gt;
        {rows.map((row, i) =&amp;gt; {
          prepareRow(row);
          return (
            &amp;lt;tr {...row.getRowProps()}&amp;gt;
              {row.cells.map((cell) =&amp;gt; {
                return &amp;lt;td {...cell.getCellProps()}&amp;gt;{cell.render('Cell')}&amp;lt;/td&amp;gt;;
              })}
            &amp;lt;/tr&amp;gt;
          );
        })}
      &amp;lt;/tbody&amp;gt;
    &amp;lt;/table&amp;gt;
  );
}


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Custom Status cell component
&lt;/h2&gt;

&lt;p&gt;Let's custom components for different cells, e.g. a show a thumbnail of the user image with the name, or a nice color-coded pill indicating the status.&lt;/p&gt;

&lt;p&gt;Let's implement a custom cell for the status.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// src/Table.js
export function StatusPill({ value }) {
  const status = value ? value.toLowerCase() : "unknown";

  return (
    &amp;lt;span
      className={classNames(
        "px-3 py-1 uppercase leading-wide font-bold text-xs rounded-full shadow-sm",
        status.startsWith("active") ? "bg-green-100 text-green-700" : null,
        status.startsWith("inactive") ? "bg-yellow-100 text-yellow-700" : null,
        status.startsWith("offline") ? "bg-red-100 text-red-700" : null
      )}
    &amp;gt;
      {status}
    &amp;lt;/span&amp;gt;
  );
}


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

&lt;/div&gt;

&lt;p&gt;Let's import this in our data and use it in the column definition.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


function Table() {
  const columns = React.useMemo(
    () =&amp;gt; [
      // ...
      {
        Header: "Status",
        accessor: "status",
        Cell: StatusPill, // new
      },
      // ...
    ],
    []
  );

  // ...
}


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

&lt;/div&gt;

&lt;p&gt;Let's check the result.&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%2F1gr4tpmcktrcawahkqdz.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%2F1gr4tpmcktrcawahkqdz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the greatness of React Table combined with the beauty of Tailwind CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding User avatar cell component
&lt;/h2&gt;

&lt;p&gt;In the first column, to show a user avatar and the email address. Let's write a component for this. plus necessary styles.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// src/Table.js
export function AvatarCell({ value, column, row }) {
  return (
    &amp;lt;div className="flex items-center"&amp;gt;
      &amp;lt;div className="flex-shrink-0 h-10 w-10"&amp;gt;
        &amp;lt;img
          className="h-10 w-10 rounded-full"
          src={row.original[column.imgAccessor]}
          alt=""
        /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div className="ml-4"&amp;gt;
        &amp;lt;div className="text-sm font-medium text-gray-900"&amp;gt;{value}&amp;lt;/div&amp;gt;
        &amp;lt;div className="text-sm text-gray-500"&amp;gt;
          {row.original[column.emailAccessor]}
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}


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

&lt;/div&gt;

&lt;p&gt;The AvatarCell takes two additional props as arguments, column and row. This is useful, because it allows you to use extra data from the object and use it within the cell.&lt;/p&gt;

&lt;p&gt;Column configuration:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// src/App.js
function App() {
  const columns = React.useMemo(() =&amp;gt; [
    {
      Header: "Name",
      accessor: "name",
      Cell: AvatarCell,
      imgAccessor: "imgUrl",
      emailAccessor: "email",
    },
    // ...
  ]);

  // ...
}


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Pagination
&lt;/h2&gt;

&lt;p&gt;The last feature I want to implement is pagination, to implement pagination, make the following changes (all of which are copied from the React Table &lt;a href="https://tanstack.com/table/v8/docs/examples/react/pagination?from=reactTableV7&amp;amp;original=https://react-table-v7.tanstack.com/docs/examples/pagination" rel="noopener noreferrer"&gt;pagination&lt;/a&gt; example)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// src/Table.js
import { ..., usePagination } from 'react-table'  // new

function Table({ columns, data }) {
    // Use the state and functions returned from useTable to build your UI
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,

    //new
    page, // Instead of using 'rows', we'll use page,
    // which has only the rows for the active page

    // The rest of these things are super handy, too ;)
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,

    state,
    preGlobalFilteredRows,
    setGlobalFilter,
  } = useTable({
      columns,
    data,
  },
    useGlobalFilter,
    usePagination,  // new
  )


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

&lt;/div&gt;

&lt;p&gt;Before we display on UI, let's customise the pagination, so as to display numbers as the pagination options. &lt;/p&gt;

&lt;p&gt;Create another file ./useCustomPagination.js&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import {useMemo} from 'react';

export const DOTS = '...';

const range = (start, end) =&amp;gt; {
    const length = end - start + 1;
    return Array.from({length}, (_, idx) =&amp;gt; idx + start);
};

export const useCustomPagination = ({totalPageCount, siblingCount = 1, currentPage}) =&amp;gt; {
    return useMemo(() =&amp;gt; {

        // Pages count is determined as siblingCount + firstPage + lastPage + currentPage + 2*DOTS
        const totalPageNumbers = siblingCount + 5;

        /*
          If the number of pages is less than the page numbers we want to show in our
          paginationComponent, we return the range [1..totalPageCount]
        */
        if (totalPageNumbers &amp;gt;= totalPageCount) {
            return range(1, totalPageCount);
        }

        const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
        const rightSiblingIndex = Math.min(
            currentPage + siblingCount,
            totalPageCount
        );

        /*
          We do not want to show dots if there is only one position left
          after/before the left/right page count as that would lead to a change if our Pagination
          component size which we do not want
        */
        const shouldShowLeftDots = leftSiblingIndex &amp;gt; 2;
        const shouldShowRightDots = rightSiblingIndex &amp;lt; totalPageCount - 2;

        const firstPageIndex = 1;
        const lastPageIndex = totalPageCount;

        if (!shouldShowLeftDots &amp;amp;&amp;amp; shouldShowRightDots) {
            const leftItemCount = 3 + 2 * siblingCount;
            const leftRange = range(1, leftItemCount);

            return [...leftRange, DOTS, totalPageCount];
        }

        if (shouldShowLeftDots &amp;amp;&amp;amp; !shouldShowRightDots) {
            const rightItemCount = 3 + 2 * siblingCount;
            const rightRange = range(
                totalPageCount - rightItemCount + 1,
                totalPageCount
            );
            return [firstPageIndex, DOTS, ...rightRange];
        }

        if (shouldShowLeftDots &amp;amp;&amp;amp; shouldShowRightDots) {
            const middleRange = range(leftSiblingIndex, rightSiblingIndex);
            return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex];
        }
    }, [totalPageCount, siblingCount, currentPage]);
};


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

&lt;/div&gt;

&lt;p&gt;import and integrate it into ./Table.js&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import {DOTS, useCustomPagination} from './useCustomPagination';


function Table({ columns, data }) {
    // Use the state and functions returned from useTable to build your UI
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,

    //new
    page, 
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,

    state,
    preGlobalFilteredRows,
    setGlobalFilter,
  } = useTable({
      columns,
    data,
  },
    useGlobalFilter,
    usePagination,  // new
  )


  const {pageIndex} = state;
            const paginationRange = useCustomPagination({
              totalPageCount: pageCount,
              currentPage: pageIndex
       }); //new

          useEffect(() =&amp;gt; {
                  setPageSize(5);
            }, [setPageSize]); //set according to your preferrence


              return (
      &amp;lt;&amp;gt;
      ...
      &amp;lt;table {...getTableProps()} border="1"&amp;gt;
        ...
        &amp;lt;tbody {...getTableBodyProps()}&amp;gt;
          {page.map((row, i) =&amp;gt; {  // replace row with page
            ...
          })}
        &amp;lt;/tbody&amp;gt;
      &amp;lt;/table&amp;gt;
      {/* new */}
            &amp;lt;div className="py-3 flex items-center text-center justify-center pt-10"&amp;gt;
        &amp;lt;div className="flex-1 flex justify-between md:hidden"&amp;gt;
          &amp;lt;Button onClick={() =&amp;gt; previousPage()} disabled={!canPreviousPage}&amp;gt;Previous&amp;lt;/Button&amp;gt;
          &amp;lt;Button onClick={() =&amp;gt; nextPage()} disabled={!canNextPage}&amp;gt;Next&amp;lt;/Button&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div className="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between" aria-label="Pagination"&amp;gt;
          &amp;lt;div className="relative z-0 inline-flex items-center ml-auto mr-auto rounded-md shadow-sm space-x-10" aria-label="Pagination"&amp;gt;
                {paginationRange?.map((pageNumber, index) =&amp;gt; {
                    if (pageNumber === DOTS) {
                        return (
                            &amp;lt;div
                            key={index}&amp;gt;...&amp;lt;/div&amp;gt;
                        );
                    }

                    if ((pageNumber - 1) === pageIndex) {
                        return (
                            &amp;lt;div
                                key={index}
                                className=' active:bg-gray-500 active:border-gray-300'
                                onClick={() =&amp;gt; gotoPage(pageNumber - 1)}&amp;gt;{pageNumber}&amp;lt;/div&amp;gt;
                        );
                    }

                    return (
                        &amp;lt;div
                            key={index}
                            className='active:bg-gray-500 active:border-gray-300'
                            onClick={() =&amp;gt; gotoPage(pageNumber - 1)}&amp;gt;{pageNumber}&amp;lt;/div&amp;gt;
                    );
                })}
             &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
           )
};


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

&lt;/div&gt;

&lt;p&gt;Note that we've replaced row with page, which is an object provided by React Table that only contains the data for the current page.&lt;/p&gt;

&lt;p&gt;In order to properly demo the pagination properly, we need a bit more data, so let's modify the getData function to concatenate the initial array three times using the JavaScript spread operator ..., before returning it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const getData = () =&amp;gt; {
  const data = [
    ...
  ]
  return [...data, ...data, ...data]
}


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

&lt;/div&gt;

&lt;p&gt;Run &lt;code&gt;npm start&lt;/code&gt; and Vula!!! &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%2Fvrd0f9u6xbmaei3s2pu8.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%2Fvrd0f9u6xbmaei3s2pu8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Style the input elements&lt;/p&gt;

&lt;p&gt;For the input elements (search field, filter drop-down and number-of-pages selector) we've relied on the default browser styling so far. Let's change that and make it fit to the rest of our design. I'll use another Tailwind plug-in for that: &lt;a href="https://github.com/tailwindlabs/tailwindcss-forms" rel="noopener noreferrer"&gt;@tailwindcss/forms&lt;/a&gt;. Check out their live demo to see examples of styles you can achieve with it.&lt;/p&gt;

&lt;p&gt;Install it with npm.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @tailwindcss/forms&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then add it to your tailwind.config.js file:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;// tailwind.config.js&lt;br&gt;
module.exports = {&lt;br&gt;
  theme: {&lt;br&gt;
    // ...&lt;br&gt;
  },&lt;br&gt;
  plugins: [&lt;br&gt;
    require("@tailwindcss/forms"),&lt;br&gt;
    // ...&lt;br&gt;
  ],&lt;br&gt;
};&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we have learnt how to create table with data grid, checkbox and pagination using React table and Tailwind CSS. I hope you enjoyed and learnt from this tutorial, kindly like, share and drop your comment and also I've provided the code repo for you, below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/OloriAsabi/imalipay-test" rel="noopener noreferrer"&gt;Code&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.samuelliedtke.com/blog/react-table-tutorial-part-1" rel="noopener noreferrer"&gt;React Table Tutorial Part 1: Style the table with Tailwind CSS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://tanstack.com/table/v8/docs/guide/introduction" rel="noopener noreferrer"&gt;React-Table&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>tailwindcss</category>
      <category>datagrid</category>
      <category>table</category>
    </item>
    <item>
      <title>Google OAuth2 using the new Google Identity Services SDK for React using Jwt-decode</title>
      <dc:creator>Olorì Àṣàbí</dc:creator>
      <pubDate>Mon, 27 Jun 2022 13:24:24 +0000</pubDate>
      <link>https://dev.to/oloriasabi/google-oauth2-using-the-new-google-identity-services-sdk-for-react-using-jwt-decode-2ioo</link>
      <guid>https://dev.to/oloriasabi/google-oauth2-using-the-new-google-identity-services-sdk-for-react-using-jwt-decode-2ioo</guid>
      <description>&lt;p&gt;In this tutorial, we will be learning how to make sign-ups stress free and hassle-free by implementing authentication via Google OAuth2 using the new Google Identity Services SDK for React @react-oauth/google🚀.&lt;/p&gt;

&lt;p&gt;You'll need&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To create-react-app React application that makes requests of your API &lt;/li&gt;
&lt;li&gt;Installation of jwt-decode &lt;/li&gt;
&lt;li&gt;Basic knowledge of React&lt;/li&gt;
&lt;li&gt;Node.js installed&lt;/li&gt;
&lt;li&gt;Code editor ( Visual Studio Code preferably )&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting  up Your Google Cloud project
&lt;/h2&gt;

&lt;p&gt;To integrate Google Login into our React app, you need a Google Client ID. First, you'll need to create a Google Cloud project.&lt;br&gt;
 &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a project and choose a name for your project.&lt;/li&gt;
&lt;/ol&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%2Fl1sb2qmq3yevwyg8dnl0.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%2Fl1sb2qmq3yevwyg8dnl0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once you have a project in place, proceed to Credentials - Create credentials - OAuth client ID.&lt;/li&gt;
&lt;/ol&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%2Fq2wm704lirw8xnp2dfi6.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%2Fq2wm704lirw8xnp2dfi6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You'll need to configure your OAuth consent screen. Choose external since we want to give access to everyone with a Google account. Google will then ask for the app's name plus some developer contact details.&lt;/li&gt;
&lt;/ol&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%2F17dihkcz7dwkc5j99p1r.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%2F17dihkcz7dwkc5j99p1r.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fill up the app registration form. For the most part, you can leave it blank.&lt;/li&gt;
&lt;/ol&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%2Fy0bxhrr5b2gbp5lugu63.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%2Fy0bxhrr5b2gbp5lugu63.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Choose the scope best suited for the app that you shall develop and fill all other necessary inputs according your application requirement.&lt;/p&gt;

&lt;p&gt;We head back to Credentials - Create credentials - OAuth client ID. Choose the Web application type and we can provide all Authorised origins and redirect URL' s.&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%2Fe5rlpos9ipq9gf42g3la.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%2Fe5rlpos9ipq9gf42g3la.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
We will see our Google client ID and a client secret. We'll only need the client ID.&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's create our React App and Login Component
&lt;/h2&gt;

&lt;p&gt;Once you have your Google Client ID, we start creating our React application to integrate Google Login.&lt;/p&gt;

&lt;p&gt;We will start with create-react-app application, and add all necessary dependencies which are Google OAuth2 using the new Google Identity Services SDK for React @react-oauth/google🚀 and jwt-decode is a small browser library that helps decoding JWTs token which are Base64Url encoded.&lt;/p&gt;

&lt;p&gt;Let's get started by running the following commands but make sure you have the necessary requirements for authenticating Google Login in React&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js installed&lt;/li&gt;
&lt;li&gt;Code editor ( Visual Studio Code preferably )&lt;/li&gt;
&lt;li&gt;Google Client ID&lt;/li&gt;
&lt;li&gt;Basic knowledge of React&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;npx create-react-app google-login&lt;br&gt;
cd google-login&lt;br&gt;
npm install @react-oauth/google jwt-decode react-router-dom&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a file named src/lib/GoogleLoginPage.js, with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { FcGoogle } from 'react-icons/fc';
import { GoogleOAuthProvider } from '@react-oauth/google';
import { GoogleLogin } from '@react-oauth/google';

const GoogleLoginPage = () =&amp;gt; {
  const responseGoogle = (response) =&amp;gt; {
    console.log(response);
  }

  return (
    &amp;lt;div className=""&amp;gt;
          &amp;lt;div className=""&amp;gt;
            &amp;lt;GoogleOAuthProvider 
                clientId={`${process.env.REACT_APP_GOOGLE_API_TOKEN}`}
                &amp;gt;
             &amp;lt;GoogleLogin
              render={(renderProps) =&amp;gt; (
                &amp;lt;button
                  type="button"
                  className=""
                  onClick={renderProps.onClick}
                  disabled={renderProps.disabled}
                &amp;gt;
                  &amp;lt;FcGoogle className="" /&amp;gt; Sign in with google
                &amp;lt;/button&amp;gt;
              )}
              onSuccess={responseGoogle}
              onFailure={responseGoogle}
              cookiePolicy="single_host_origin"
            /&amp;gt;
            &amp;lt;/GoogleOAuthProvider&amp;gt;
          &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}

export default GoogleLoginPage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run npm start and check your console to receive your encoded token which we will decode using jwt-decode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decoding Google Token using JWT-DECODE
&lt;/h3&gt;

&lt;p&gt;Now that we have gotten our google response token, lets decode to get all necessary user info.&lt;/p&gt;

&lt;p&gt;Still in the GoogleLoginPage.js let's update it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { useNavigate } from 'react-router-dom';
import { FcGoogle } from 'react-icons/fc';
import { GoogleOAuthProvider } from '@react-oauth/google';
import { GoogleLogin } from '@react-oauth/google';
import { client } from '../client';
import jwt_decode from "jwt-decode";

const GoogleLoginPage = () =&amp;gt; {
  const navigate = useNavigate();

  const responseGoogle = (response) =&amp;gt; {
   //console.log(response);
    const userObject = jwt_decode(response.credential);
    //console.log(userObject);
    localStorage.setItem('user', JSON.stringify(userObject));
    const { name, sub, picture } = userObject;
    const doc = {
      _id: sub,
      _type: 'user',
      userName: name,
      image: picture,
    };
    client.createIfNotExists(doc).then(() =&amp;gt; {
      navigate('/', { replace: true });
    });

  }

  return (
    &amp;lt;div className=""&amp;gt;
          &amp;lt;div className=""&amp;gt;
            &amp;lt;GoogleOAuthProvider 
                clientId={`${process.env.REACT_APP_GOOGLE_API_TOKEN}`}
                &amp;gt;
             &amp;lt;GoogleLogin
              render={(renderProps) =&amp;gt; (
                &amp;lt;button
                  type="button"
                  className=""
                  onClick={renderProps.onClick}
                  disabled={renderProps.disabled}
                &amp;gt;
                  &amp;lt;FcGoogle className="" /&amp;gt; Sign in with google
                &amp;lt;/button&amp;gt;
              )}
              onSuccess={responseGoogle}
              onFailure={responseGoogle}
              cookiePolicy="single_host_origin"
            /&amp;gt;
            &amp;lt;/GoogleOAuthProvider&amp;gt;
          &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}

export default GoogleLoginPage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's do a break down of what we just did.&lt;/p&gt;

&lt;p&gt;After getting our Google Login response in our responseGoogle() , we created a variable to store the decoded token by importing jwt-decode package and calling the response we got from our google login.&lt;/p&gt;

&lt;p&gt;Now that the token has been decoded, we can now get our user info, store it into our localStorage, de-structure the necessary needed info and send it to the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reconfigure Google OAuth
&lt;/h2&gt;

&lt;p&gt;Lastly don't forget to configure all necessary Authorised JavaScript origins and Authorised redirect URIs in your Google API.&lt;/p&gt;

&lt;p&gt;Hurray!!! we can now view, enjoy and test our finished application&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%2Fbff4aljyb0k02xw9l0ii.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%2Fbff4aljyb0k02xw9l0ii.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://socials-website.netlify.app/" rel="noopener noreferrer"&gt;You can check out the live demo here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/OloriAsabi/socials" rel="noopener noreferrer"&gt;You can view and download our source code at&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we have learnt how to Authenticate User with the Google OAuth2 using the new Google Identity Services SDK for React @react-oauth/google🚀 and decoding token with JWT-DECODE.&lt;br&gt;
 &lt;br&gt;
I really hope you learnt something new today, don't forget to like, share and comment. &lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Google OAuth2 using the new &lt;a href="https://developers.google.com/identity/gsi/web" rel="noopener noreferrer"&gt;Google Identity Services SD&lt;/a&gt;K for React &lt;a href="https://www.npmjs.com/package/@react-oauth/google" rel="noopener noreferrer"&gt;@react-oauth/google🚀&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/jwt-decode" rel="noopener noreferrer"&gt;Decoding JWTs token which are Base64Url encoded.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>googleoauth2</category>
      <category>jwt</category>
      <category>programming</category>
      <category>react</category>
    </item>
    <item>
      <title>Creating an Authentication Form using React Hook Form, React and Firebase.</title>
      <dc:creator>Olorì Àṣàbí</dc:creator>
      <pubDate>Mon, 27 Jun 2022 09:35:16 +0000</pubDate>
      <link>https://dev.to/oloriasabi/creating-an-authentication-form-using-react-hook-form-react-and-firebase-5d9h</link>
      <guid>https://dev.to/oloriasabi/creating-an-authentication-form-using-react-hook-form-react-and-firebase-5d9h</guid>
      <description>&lt;p&gt;In this tutorial , we’ll be setting up our own Firebase project through the Firebase Console to setup user registration and authentication in our React application. Firebase simplifies the process of user authentication by providing all necessary functions and SDK to be integrated in your project and allowing you to focus on other parts of the development process.&lt;/p&gt;

&lt;p&gt;Let’s get started by creating our application using Create React App and installing the Firebase, managing User State with React Context API and React Router dependencies by running the following commands but make sure you have the necessary requirements for authenticating with Firebase in React&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js installed&lt;/li&gt;
&lt;li&gt;Code editor ( Visual Studio Code preferably )&lt;/li&gt;
&lt;li&gt;Google account which will be to used in Firebase&lt;/li&gt;
&lt;li&gt;Basic knowledge of React
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app react-auth-form
cd react-auth-form
npm install firebase react-router-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a Firebase account and add a "New Project".&lt;/p&gt;

&lt;p&gt;Follow the provided prompts to complete the setup and you'll end up here:&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%2Fawmb67apjxmhyhs0hd5f.jpg" 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%2Fawmb67apjxmhyhs0hd5f.jpg" alt="Image description" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add Firebase to your app use the web option (&amp;lt;/&amp;gt;).&lt;/p&gt;

&lt;p&gt;To complete the Firebase setup we need to specify an authentication method. There are quite a number of options of methods available but for this tutorial we'll be using the email and password method. Navigate to "Authentication" -&amp;gt; "Sign-in Method" and change the "Email/Password" status setting to "Enabled".&lt;/p&gt;

&lt;h2&gt;
  
  
  Firebase config
&lt;/h2&gt;

&lt;p&gt;Create a new file in the following location - src/firebase.js.&lt;/p&gt;

&lt;p&gt;This file import's the Firebase SDK and contains the Firebase configuration settings and setting all inputs into your .env file with the standard variable names for secured purposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { initializeApp } from "firebase/app"
import { getAuth } from "firebase/auth"
import "firebase/auth"
import { getFirestore } from '@firebase/firestore';

const firebaseConfig = {
    apiKey: process.env.REACT_APP_FIREBASE_KEY,
    authDomain: process.env.REACT_APP_FIREBASE_DOMAIN,
    projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
    storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_FIREBASE_SENDER_ID,
    appId: process.env.REACT_APP_FIREBASE_APP_ID,
    measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
};

export const app = initializeApp(firebaseConfig)
export const auth = getAuth(app)
export const db = getFirestore(app);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy these setting from "Project Settings" - "General" in the Firebase console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Register users using React-hook-form
&lt;/h2&gt;

&lt;p&gt;Create a new file in the following location - src/components/Register.js.&lt;/p&gt;

&lt;p&gt;This component contains a sign up form so users can create accounts using react-hook-form:&lt;br&gt;
To install React Hook Form, run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install react-hook-form&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;First, import the useForm Hook from the installedreact-hook-form package:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { useForm } from "react-hook-form";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, inside your component, use the Hook as follows to validate errors, submit data and register:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const { handleSubmit, formState: { errors }, trigger, register, watch } = useForm();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To apply validations to a field in the form input, you can pass validation parameters to the register method. Validation parameters are similar to the existing HTML form validation standard.&lt;/p&gt;

&lt;p&gt;These validation parameters include the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;required indicates if the field is required or not. If this property is set to true, then the field cannot be empty&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;minlength and maxlength set the minimum and maximum length for a string input value&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;min and max set the minimum and maximum values for a numerical value&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;type indicates the type of the input field; it can be email, number, text, or any other standard HTML input types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;pattern defines a pattern for the input value using a regular expression&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now lets collect data and register with firebase&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import { createUserWithEmailAndPassword } from 'firebase/auth';
import { useForm } from 'react-hook-form';

const Register = ({ history }) =&amp;gt; {
    const {
    handleSubmit,
    formState: { errors },
    trigger,
    register,
    watch
    } = useForm();

    async function onhandleSubmit(data) {
     //console.log(data)
        try {
        await createUserWithEmailAndPassword(
        auth, data.email, data.password, data.name)
        history.push("/");
        alert ("User Created Successfully")
        } catch (error) {
        console.log(error)
        alert ("User created failed")
        alert(error);
      }
    }

 return (
  &amp;lt;div&amp;gt;
    &amp;lt;Form onSubmit={handleSubmit(onhandleSubmit)}&amp;gt;
      &amp;lt;h5&amp;gt;Create an account&amp;lt;/h5&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;div&amp;gt;
         &amp;lt;label&amp;gt;Your email address&amp;lt;/label&amp;gt;
          &amp;lt;input
            id="email"
            name="email"
            type= 'email'
            required={true}
            {...register("email", {
            required: "Email is Required!!!" ,
            pattern: {
            value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
            message: "Invalid email address",
            }})}
            error={Boolean(errors.email)}
            onKeyUp={() =&amp;gt; {trigger("email")}}
          &amp;gt;&amp;lt;/input&amp;gt;
          {errors.email &amp;amp;&amp;amp; (
          &amp;lt;small className="text-danger"&amp;gt;{errors.email.message}&amp;lt;/small&amp;gt;
          )}
        &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Your password&amp;lt;/label&amp;gt;
        &amp;lt;input
           name='password'
           id="password"
           type= 'password'
           autoComplete='off'
           className={`form-control ${errors.password &amp;amp;&amp;amp; "invalid"}`}
           required={true}
           {...register("password", {
           required: "You must specify a password",
           pattern: {
           value: '^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){    1,})(?!.*\s).{8,}$',
           message: "Password should contain at least one number and one    special character"
           },
          minLength: {
          value: 8,
          message: "Password must be more than 8 characters"
          },
          maxLength: {
          value: 20,
          message: "Password must be less than 20 characters"
          },
          })}
          onKeyUp={() =&amp;gt; {trigger("password")}}
          error={Boolean(errors.password)}
        &amp;gt;&amp;lt;/input&amp;gt;
          {errors.password &amp;amp;&amp;amp; (
          &amp;lt;small className="text-danger"&amp;gt;{errors.password.message}&amp;lt;/small&amp;gt;
          )}
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Confirm your password&amp;lt;/label&amp;gt;
        &amp;lt;input
           id="confirmPassword"
           name="confirmPassword"
           type='password'
           {...register( 'confirmPassword', {
           validate: value =&amp;gt;
           value === watch("password", "") || "The passwords do not match"
           })}
           autoComplete='off'
           onPaste={(e) =&amp;gt;{
           e.preventDefault();
           return false
           }}
           error={Boolean(errors.confirmPassword)}
           className={`form-control ${errors.confirmPassword &amp;amp;&amp;amp; "invalid"}`}
           required={true}
           onKeyUp={() =&amp;gt; {trigger("confirmPassowrd")}}
         /&amp;gt;
           {errors.confirmPassword &amp;amp;&amp;amp; (
           &amp;lt;small className="text-danger"&amp;gt;{errors.confirmPassword.message}    &amp;lt;/small&amp;gt;
           )}
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;Your full name&amp;lt;/label&amp;gt;
        &amp;lt;input
           name='name'
           type="name"
           className={`form-control ${errors.name &amp;amp;&amp;amp; "invalid"}`}
           required={true}
           defaultValue=""
          {...register("name", { required: "Fullname is Required!!!" })}
          onKeyUp={() =&amp;gt; {trigger("name")}}/&amp;gt;
          {errors.name &amp;amp;&amp;amp; (
          &amp;lt;small className="text-danger"&amp;gt;Fullname is Required!!!&amp;lt;/small&amp;gt;
         )}
        &amp;lt;/div&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;button&amp;gt;Create an account&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/Form&amp;gt;
  &amp;lt;/div&amp;gt;
)}
export default withRouter(Register)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Managing User State with React Context API
&lt;/h2&gt;

&lt;p&gt;Context API is a way to share data with components at any level of the React component tree without having to pass it down as props. Since a user might be required by a different component in the tree, using the Context API is great for managing the user state.&lt;/p&gt;

&lt;p&gt;Before we start using the Context API, there are a few things we need to set up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a context object using the createContext() method&lt;/li&gt;
&lt;li&gt;Pass the components we want to share the user state with as children of Context.Provider&lt;/li&gt;
&lt;li&gt;Pass the value we want the children/consuming component to access as props to Context.Provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get to it. In the src directory, create an AuthContext.js file and add the following lines of code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect, useState, useContext } from "react";
import { auth } from "./api";
import {
  createUserWithEmailAndPassword, 
  onAuthStateChanged,
  sendPasswordResetEmail,
  signInWithEmailAndPassword } from "firebase/auth";

export const AuthContext = React.createContext();

export function useAuth() {
  return useContext(AuthContext)
}

export const AuthProvider = ({ children }) =&amp;gt; {
  const [currentUser, setCurrentUser] = useState(null);
  const [pending, setPending] = useState(true);

  function signup(email, password, name) {
   return createUserWithEmailAndPassword(auth, email, password, name)
  }

  function login(email, password) {
   return signInWithEmailAndPassword(auth ,email, password)
  }
  function logout() {
    return auth.signOut()
  }

  function resetPassword(email) {
    return sendPasswordResetEmail(auth, email)
  }

  function updateEmail(email) {
   return currentUser.updateEmail(email)
  }

  function updatePassword(password) {
    return currentUser.updatePassword(password)
  }
  useEffect(() =&amp;gt; {
   const unsubscribe = onAuthStateChanged(auth, user =&amp;gt; {
    setCurrentUser(user)
    setPending(false)
   });
   return unsubscribe
  }, []);

  if(pending){
    return &amp;lt;&amp;gt;Loading...&amp;lt;/&amp;gt;
  }

  const value = {
      currentUser,
      login,
      signup,
      logout,
      resetPassword,
      updateEmail,
      updatePassword
   }
    return (
      &amp;lt;AuthContext.Provider
      value={value}
      &amp;gt;
       {children}
      &amp;lt;/AuthContext.Provider&amp;gt;
    );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new file in the following location — src/components/Login.js.&lt;/p&gt;

&lt;p&gt;This component contains the log in form so users can sign into their account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useContext } from "react";
import { Redirect } from "react-router-dom";
import { AuthContext } from "./Auth";
import firebaseConfig from "../firebase.js";
import { useForm, Controller } from 'react-hook-form';

const Login = () =&amp;gt; {

  const {
   handleSubmit,
   control,
   formState: { errors },
  } = useForm();

  const submitHandler = async ({ email, password }) =&amp;gt; {
    await try {
        firebaseConfig.auth().signInWithEmailAndPassword(email,   password);
      } catch (error) {
        alert(error);
      }
    };

    const { currentUser } = useContext(AuthContext);

    if (currentUser) {
      return &amp;lt;Redirect to="/dashboard" /&amp;gt;;
    }
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Log In&amp;lt;/h1&amp;gt;
      &amp;lt;form onSubmit={handleSubmit(submitHandler)}&amp;gt;
        &amp;lt;label for="email"&amp;gt;Email&amp;lt;/label&amp;gt;
        &amp;lt;input
         id="email"
         name="email"
         type= 'email'
         required={true}
         {...register("email", {
          required: "Email is Required!!!",
          pattern: {
          value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
           message: "Invalid email address",
           }})}
           error={Boolean(errors.email)}
           onKeyUp={() =&amp;gt; {trigger("email")}}
          &amp;gt;&amp;lt;/input&amp;gt;
        {errors.email &amp;amp;&amp;amp; (
         &amp;lt;small className="text-danger"&amp;gt;{errors.email.message}&amp;lt;/small&amp;gt;
        )}
       &amp;lt;/div&amp;gt;
       &amp;lt;div&amp;gt;
       &amp;lt;label&amp;gt;Your password&amp;lt;/label&amp;gt;
       &amp;lt;input
         name='password'
         id="password"
         type= 'password'
         autoComplete='off'
         className={`form-control ${errors.password &amp;amp;&amp;amp; "invalid"}`}
         required={true}
         {...register("password", {
         required: "You must specify a password", 
         pattern: {
         value: '^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})
         (?=. (.*.      [\W]){    1,})(?!.*\s).{8,}$',
         message: "Password should contain at least one number
         and      one    special character"
          },
         minLength: {
         value: 8,
          message: "Password must be more than 8 characters"
           },
           maxLength: {
          value: 20,
          message: "Password must be less than 20 characters"
          },
          })}
          onKeyUp={() =&amp;gt; {trigger("password")}}
          error={Boolean(errors.password)}
           &amp;gt;&amp;lt;/input&amp;gt;
          {errors.password &amp;amp;&amp;amp; (
          &amp;lt;small className="text-danger"&amp;gt;  
          {errors.password.message}
          &amp;lt;/small&amp;gt;
          )}
       &amp;lt;/div&amp;gt;        
        &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/&amp;gt;
  );
};
export default Login;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the current user is already logged in they’ll get redirected to the home page. Otherwise we capture the form input on submit and send the details to the Firebase Authentication signInWithEmailAndPassword method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Home page
&lt;/h2&gt;

&lt;p&gt;Create a new file in the following location — src/components/Home.js.&lt;/p&gt;

&lt;p&gt;This component contains content that can only be viewed by authenticated users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { useAuth } from '../../services/auth';
import { useState } from 'react';
import { useHistory } from 'react-router-dom';

const Home = () =&amp;gt; {
  const [error, setError] = useState("")
  const { currentUser, logout } = useAuth()
  const history = useHistory()

  async function handleLogout() {
    setError("")
    try {
      await logout()
      history.push("/login")
   } catch {
      setError("Failed to log out")
          }
   }

return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;This is the Home Page, if you can see this you're logged in.
       &amp;lt;/p&amp;gt;
      &amp;lt;button onClick={handleLogout}&amp;gt;Sign out&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};
export default Home;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this page is accessed by a non-authenticated user the browser will re-direct to the login page. If the user is authenticated we display the private content. We’ve also included a button so users can sign out of their account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pulling it all together in App.js
&lt;/h2&gt;

&lt;p&gt;Modify the App.js file to include the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import './App.css';
import {
BrowserRouter as Router,
Route,
} from "react-router-dom";
import Register from "./pages/Register/Register";
import Login from "./pages/Login/Login";
import { AuthProvider } from "./services/auth";
import PrivateRoute from "./PrivateRoute";
import Profile from "./pages/Profile/Profile";
import Home from "./pages/Home/Home";

function App() {

return (
  &amp;lt;AuthProvider&amp;gt;
    &amp;lt;Router&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;PrivateRoute exact path="/" component={Home} /&amp;gt;
        &amp;lt;Route  path="/login" component={Login} /&amp;gt;
        &amp;lt;Route path="/register" component={Register} /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/Router&amp;gt;
  &amp;lt;/AuthProvider&amp;gt;
)}
export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now run npm start to start the application and test out the registration and authentication process. Once the sign up form has been submitted you can browse to “Authentication” - “Users” in the Firebase console to confirm registration was successful and manage user accounts.&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%2Fbxi5g0x2w889se8k93ba.jpg" 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%2Fbxi5g0x2w889se8k93ba.jpg" alt="Image description" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now know how to authenticate users in your React applications using Firebase. If you would like to learn more about Firebase Authentication, I’d suggest checking out the official guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we have learned how to use of the Firebase Authentication to build user registration and authentication service in React using React Hook Form for form validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://firebase.google.com/docs/auth/web/start" rel="noopener noreferrer"&gt;Get Started with Firebase Authentication on Websites &lt;/a&gt;(Firebase documentation)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react-hook-form.com/get-started#Quickstart" rel="noopener noreferrer"&gt;Form Validation using React Hook Form&lt;/a&gt; (React Hook Form documentation)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://firebase.google.com/docs/auth/web/manage-users" rel="noopener noreferrer"&gt;Manage Users in Firebase (&lt;/a&gt;Firebase Users documentation)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;Managing User State with React Context API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>react</category>
      <category>firebase</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
