ReactJS-The Beginner Master Class
  • React In the Beginning
    • Lesson 1 - Demo: Build a Simple React App - Fast
    • Lesson 2 - HTML Review
    • Lesson 3 - CSS Review
    • Lesson 4 - Modern JavaScript (JSX) Patterns
    • Lesson 5 - Set up Dev Environment
    • Hands-on Practice
  • React Fundamentals
    • Lesson 1 - Understanding Old vs New Way of Building Web Apps - SPAs
    • Lesson 2 - Motivation for Using React as the Solution to Vanilla JS
    • Lesson 3 - What is ReactJS - How it Works
    • React Code Along from Scratch
    • Lesson 4 - Create and Run a React Project with Vite - Full Overview
    • Lesson 5 - Create Hook by State Management in React
    • Lesson 6 - React Project File and Folder Walkthrough
    • Lesson 7 - JSX and How React Treats the DOM & JSX Compilation(by Babeljs) - Overview
    • Lesson 8 - Understanding the Main Files - App.jsx and main.jsx
    • Lesson 9 - Props and One-Way Data Flow - Overview
    • Lesson 10 - Google Bookshelf App - Ver 1.0
    • Hands-on Practice I
    • Hands-on Practice II
  • React State and Styling
    • Lesson 1 - Pulling Book Data from a Different Data File
    • Lesson 2 - Overview of How State Works in React
    • Lesson 3 - RandomQuote App
    • Lesson 4 - Lifting State Up - React Pattern Overview
    • Hands-On - Simple Counter
  • Forms and Interactivity - Grocery List App
    • Lesson 1 - Setup a Simple Form and Input
    • Lesson 2 - Build Form Profile App Using Multi-input Form Data
    • Hands-on : Build a Grocery List App
  • Connecting to the Backend - Consuming APIs - UseEffect Hook
    • Lesson 1 - Connecting to the Back End - Understanding Side Effects, Hooks and useEffect - Overview
    • Lesson 2 - Fetching Data from the Backend the Right Way with useEffect Hook
    • Lesson 3 - Setting Up Loading State
    • Hands-on :Use Dependency Array and Adding Values that Control Side Effects
  • Solo Project 1
  • RESTful APIs :Build a BookSearch App -Ver 2.0
    • Lesson 1: Build and test RESTful APIs with Postman
    • Lesson 2 - BookShelf App Structure
    • Lesson 3 - Create NavBar.jsx Component
    • Lesson 4 - Create Footer Component
    • Lesson 5 - Create BookList.jsx Component
    • Lesson 6 - Create BookCard.jsx Component
    • Lesson 7 - Creating Custom Hooks - useBooks and api-client
    • Lesson 8 - Controlling Network Activities in React with AbortController
    • Lesson 9 - Show Book Details in a Modal - Working
    • Lesson 10 - Bookshelf App Summary
  • Multi-Page Applications (MPAs)
    • Build a Multi-Page React Application
    • Multi-Page React Application
    • Hands-on Practice
  • Backend Frameworks-NEXT.JS
    • Migrating from React to Next.js
    • Lesson 1: Key Concepts of NodeJS and Express for Backend Web Development
    • Lesson 2: How to set up a new Next.js project
    • Lesson 3: How to create Layouts and Pages
    • Hands-on Practice 1
    • Hands on Practice 2
      • New Project & Folder Structure
      • File-Based Routing
      • Server vs Client Components & Router Hooks
      • Start On The Navbar
      • Navbar Links, Dropdowns & React Icons
      • Active Links & Conditional Rendering
      • Homepage Components
      • Properties Page
      • Property Card Dynamic Data
      • Home Property Listings
      • Custom Not Found & Loading Pages
  • Git and GitHubs
    • Git Installation
    • Git Commands
    • GitHub Repository
    • Hands-on Practice
  • Database in Application
    • React Supabase CRUD
    • Hands-on: Note Taking App
  • NoSQL Database
    • Installing MongoDB Community Edition
    • System Env Path Setting
    • How to use MongoDB Shell
    • How to Connect and Use Mongosh in VS Code via MongoDB Extension
    • MongoDB Guide
  • Solo Project 2
  • Deployment and Web Hosting
    • Lesson 1. React+Vite+TS+Shadcn Project
    • Lesson 2. Deploying a React Vite App to Vercel from Vercel CLI
    • Lesson 3 Connecting to GitHub Repo and Automate Deployment
  • Solo Project 3
  • Final Term Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 2 Team Project
    • Level 2 Team Project
    • Level 3 Team Project
    • Level 3 Team Project
Powered by GitBook
On this page
  • Building Form Profile App
  • Step-by-Step Procedure to Implement React Form Profile App
  • 1. Setting Up the Project
  • 2. Implement the Parent Component: AppFormProfile.jsx
  • Challenge : Update the component to fetch image URLs from Unsplash and allow the user to select one.
  1. Forms and Interactivity - Grocery List App

Lesson 2 - Build Form Profile App Using Multi-input Form Data

PreviousLesson 1 - Setup a Simple Form and InputNextHands-on : Build a Grocery List App

Last updated 1 month ago

Building Form Profile App

Step-by-Step Procedure to Implement React Form Profile App

1. Setting Up the Project

  1. Create a New React Project: Run the following command to create a new React project:

    npx create-react-app react-formProfile-app
    cd react-formProfile-app
  2. Install Bootstrap CSS: Install Bootstrap using npm:

    npm install bootstrap

    Import Bootstrap in the main.jsx file:

    import 'bootstrap/dist/css/bootstrap.min.css';
  3. Setup Folder Structure: Create a components folder inside the src directory:

    src/
    |-- components/
        |-- FormProfile.jsx
    |-- AppFormProfile.jsx

2. Implement the Parent Component: AppFormProfile.jsx

The parent component manages the state for the form data and profiles, and passes the necessary props to the child component.

Code for AppFormProfile.jsx:

import React, { useState } from 'react';
import FormProfile from './components/FormProfile';
import 'bootstrap/dist/css/bootstrap.min.css';

function AppFormProfile() {
  const [formData, setFormData] = useState({
    userImage: './src/assets/IMG_0003.JPG', // Replace with a real image URL,
    name: '',
    email: '',
    profession: ''
  });

  const [profiles, setProfiles] = useState([]);

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData({
      ...formData,  // create a copy of the formData array.
      [name]: value
    }); //update form data input
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    setProfiles([...profiles, formData]);
    setFormData({ userImage: '', name: '', email: '', profession: '' });
  }; //clear form inputs

  return (
    <div className="container mt-5">
      <h1 className="text-center">React Profile App</h1>
      <form onSubmit={handleSubmit} className="mb-4">
        <div className="mb-3">
          <input
            type="text"
            name="userImage"
            value={formData.userImage}
            onChange={handleChange}
            placeholder="Image URL"
            className="form-control"
          />
        </div>
        <div className="mb-3">
          <input
            type="text"
            name="name"
            value={formData.name}
            onChange={handleChange}
            placeholder="Name"
            className="form-control"
          />
        </div>
        <div className="mb-3">
          <input
            type="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
            placeholder="Email"
            className="form-control"
          />
        </div>
        <div className="mb-3">
          <input
            type="text"
            name="profession"
            value={formData.profession}
            onChange={handleChange}
            placeholder="Profession"
            className="form-control"
          />
        </div>
        <button type="submit" className="btn btn-primary">Add Profile</button>
      </form>
      <div className="profile-container d-flex flex-wrap gap-4">
        {profiles.map((profile, index) => (
          <FormProfile
            key={index}
            userImage={profile.userImage}
            name={profile.name}
            email={profile.email}
            profession={profile.profession}
          />
        ))}
      </div>
    </div>
  );
}

export default AppFormProfile;

3. Implement the Child Component: FormProfile.jsx

The child component receives props from the parent and renders the user profile.

Code for FormProfile.jsx:

import React from 'react';
import PropTypes from 'prop-types';

function FormProfile({ userImage, name, email, profession }) {
  return (
    <div className="user-profile d-flex border p-3 rounded">
      <div className="left-item me-3">
        <img src={userImage} alt={name} className="img-fluid rounded" style={{ width: '100px', height: '100px' }} />
      </div>
      <div className="right-item d-flex flex-column">
        <h5>{name}</h5>
        <p>{email}</p>
        <p>{profession}</p>
      </div>
    </div>
  );
}

FormProfile.propTypes = {
  userImage: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  email: PropTypes.string.isRequired,
  profession: PropTypes.string.isRequired,
};

export default FormProfile;

4. Styling with Bootstrap

Leverage Bootstrap classes for styling. Use d-flex, flex-row, and flex-column for layouts. Add custom styles in App.css if necessary.

5. Run the Application

Start the application using the following command:

npm run dev

Final Output

The app will display a form at the top for adding profiles. Below the form, profiles will be displayed in a flexbox layout with images on the left and details on the right.

Summary

This walkthrough demonstrates how to:

  1. Lift state up in the parent component.

  2. Pass props to child components.

  3. Use Bootstrap for responsive styling.

  4. Manage forms and lists dynamically in React.

Challenge : Update the component to fetch image URLs from Unsplash and allow the user to select one.

Code for Updated AppFormProfileUpdated.jsx:

import React, { useState, useEffect } from 'react';
import FormProfileUpdated from './components/FormProfileUpdated.jsx';
const apiKey =''

function AppFormProfileUpdated() {
  const [formData, setFormData] = useState({
    userImage:'https://images.pexels.com/photos/2014422/pexels-photo-2014422.jpeg',
    name: '',
    email: '',
    profession: ''
  });

  const [profiles, setProfiles] = useState([]);
  const [imageOptions, setImageOptions] = useState([]);
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState(null)

  useEffect(() => {
    // Fetch image options from Unsplash
      const fetchImages = async (query) => {
      setIsLoading(true)
      try {
        const response = await fetch(
          `https://api.pexels.com/v1/search?query=${query}&per_page=2`,
          {
            headers: {
              Authorization: apiKey,
            },
          },
        )

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`)
        }

        const data = await response.json()
        setImageOptions(data.photos)
    
        console.log("Photos: ", data.photos)
      } catch (error) {
        setError('Failed to fetch images.')
      } finally {
        setIsLoading(false)
      }
    }

    fetchImages('people')
  }, []);

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData({
      ...formData,
      [name]: value
    });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    setProfiles([...profiles, formData]);
    setFormData({ userImage: '', name: '', email: '', profession: '' });
  };

  return (
    <div className="container mt-5">
      <h1 className="text-center">React Profile App</h1>
      <form onSubmit={handleSubmit} className="mb-4">
        <div className="mb-3">
          <label htmlFor="userImage" className="form-label">Select an Image:</label>
          <select
            id="userImage"
            name="userImage"
            value={formData.userImage}
            onChange={handleChange}
            className="form-select"
          >
            <option value="">Choose an image</option>
            {imageOptions.map((url, index) => (
              <option key={index} value={url}>{url}</option>
            ))}
          </select>
        </div>
        <div className="mb-3">
          <input
            type="text"
            name="name"
            value={formData.name}
            onChange={handleChange}
            placeholder="Name"
            className="form-control"
          />
        </div>
        <div className="mb-3">
          <input
            type="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
            placeholder="Email"
            className="form-control"
          />
        </div>
        <div className="mb-3">
          <input
            type="text"
            name="profession"
            value={formData.profession}
            onChange={handleChange}
            placeholder="Profession"
            className="form-control"
          />
        </div>
        <button type="submit" className="btn btn-primary">Add Profile</button>
      </form>
      <div className="profile-container d-flex flex-wrap gap-4">
        {profiles.map((profile, index) => (
          <FormProfileUpdated
            key={index}
            userImage={profile.userImage}
            name={profile.name}
            email={profile.email}
            profession={profile.profession}
          />
        ))}
      </div>
    </div>
  );
}

export default AppFormProfileUpdated;

3. Implement the Child Component: FormProfile.jsx

The child component receives props from the parent and renders the user profile.

Code for FormProfileUpdated.jsx

import React from 'react';
import PropTypes from 'prop-types';

function FormProfileUpdated({ userImage, name, email, profession }) {
  return (
    <div className="user-profile d-flex border p-3 rounded">
      <div className="left-item me-3">
        <img src={userImage} alt={name} className="img-fluid rounded" style={{ width: '100px', height: '100px' }} />
      </div>
      <div className="right-item d-flex flex-column">
        <h5>{name}</h5>
        <p>{email}</p>
        <p>{profession}</p>
      </div>
    </div>
  );
}

FormProfile.propTypes = {
  userImage: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  email: PropTypes.string.isRequired,
  profession: PropTypes.string.isRequired,
};

export default FormProfileUpdated;

4. Styling with Bootstrap

Leverage Bootstrap classes for styling. Use d-flex, flex-row, and flex-column for layouts. Add custom styles in App.css if necessary.

5. Run the Application

Start the application using the following command:

npm run dev

Final Output

The app will display a form at the top for adding profiles. Below the form, profiles will be displayed in a flexbox layout with images on the left and details on the right.

Challenge : Capture Live Image from PC Camera

I want to modify App.jsx react component to capture the image data from the usb pc camera instead of using image URL.

// App.jsx
import { useState } from 'react'
import './App.css'
import 'bootstrap/dist/css/bootstrap.css'
import FormProfile from './components/FormProfile.jsx'


function App() {
  const [formData, setFormData] = useState({
    userImage: './src/assets/IMG_0003.JPG', // Replace with a real image URL,
    name: '',
    email: '',
    profession: '',
  })

  const [profiles, setProfiles] = useState([])

  const handleChange = (event) => {
    const { name, value } = event.target
    setFormData({
      ...formData,
      [name]: value,
    }) //update form data input
  }

  const handleSubmit = (event) => {
    event.preventDefault()
    setProfiles([...profiles, formData])
    setFormData({ userImage: '', name: '', email: '', profession: '' })//clear form inputs
  }

  return (
    <>
      <h1>Form Profile App</h1>
      <div className="container mt-5 col col-md-8">
        <form onSubmit={handleSubmit} className="mb-4">
          <div className="mb-3">
            <input
              type="text"
              name="userImage"
              value={formData.userImage}
              onChange={handleChange}
              placeholder="Enter image url .e.g.,  https://unsplash.com/t/people"
              className="form-control"
              required="true"
            />
          </div>
          <div className="mb-3">
            <input
              type="text"
              name="name"
              value={formData.name}
              onChange={handleChange}
              placeholder="Name"
              className="form-control"
              required="true"
            />
          </div>
          <div className="mb-3">
            <input
              type="email"
              name="email"
              value={formData.email}
              onChange={handleChange}
              placeholder="Email"
              className="form-control"
              required="true"
            />
          </div>
          <div className="mb-3">
            <input
              type="text"
              name="profession"
              value={formData.profession}
              onChange={handleChange}
              placeholder="Profession"
              className="form-control"
              required="true"
            />
          </div>
          <button type="submit" className="btn btn-primary">
            Add Profile
          </button>
        </form>
        <div className="profile-container d-flex flex-wrap gap-4 ">
          {profiles.map((profile, index) => (
            <FormProfile
              key={index}
              userImage={profile.userImage}
              name={profile.name}
              email={profile.email}
              profession={profile.profession}
            />
          ))}
        </div>
      </div>
    </>
  )
}

export default App
// AppVideoProfile.jsx
import { useState, useRef, useEffect } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import FormProfile from './components/FormProfile.jsx';

function App() {
  const [formData, setFormData] = useState({
    userImage: '',
    name: '',
    email: '',
    profession: '',
  });

  const [profiles, setProfiles] = useState([]);
  const videoRef = useRef(null);
  const [cameraStream, setCameraStream] = useState(null);


  useEffect(() => {
    // Access the user's camera
    navigator.mediaDevices.getUserMedia({ video: true })
      .then((stream) => {
        setCameraStream(stream);
        if (videoRef.current) {
          videoRef.current.srcObject = stream;
        }
      })
      .catch((error) => {
        console.error('Error accessing camera:', error);
      });

    return () => {
      // Clean up the stream when the component unmounts
      if (cameraStream) {
        cameraStream.getTracks().forEach(track => track.stop());
      }
    };
  }, []);

  const captureImage = () => {
    if (cameraStream && videoRef.current) {
      const canvas = document.createElement('canvas');
      canvas.width = videoRef.current.videoWidth;
      canvas.height = videoRef.current.videoHeight;
      const context = canvas.getContext('2d');
      context.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height);

      const imageDataURL = canvas.toDataURL('image/png');
      setFormData({
        ...formData,
        userImage: imageDataURL,
      });
    }
  };

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData({
      ...formData,
      [name]: value,
    });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    setProfiles([...profiles, formData]);
    setFormData({ userImage: '', name: '', email: '', profession: '' });
  };

  return (
    <>
      <h1>Form Profile App</h1>
      <div className="container mt-5 col col-md-8">
        <form onSubmit={handleSubmit} className="mb-4">
          <div className="mb-3">
            <video ref={videoRef} autoPlay playsInline />
            <button onClick={captureImage} type="button" className="btn btn-secondary mt-2">Capture Image</button>          
            {formData.userImage && <img src={formData.userImage} alt="Captured" style={{ maxWidth: '200px' }} />}
          </div>
          {/* ... other input fields (name, email, profession) */}
           <div className="mb-3">
            <input
              type="text"
              name="name"
              value={formData.name}
              onChange={handleChange}
              placeholder="Name"
              className="form-control"
              required="true"
            />
          </div>
          <div className="mb-3">
            <input
              type="email"
              name="email"
              value={formData.email}
              onChange={handleChange}
              placeholder="Email"
              className="form-control"
              required="true"
            />
          </div>
          <div className="mb-3">
            <input
              type="text"
              name="profession"
              value={formData.profession}
              onChange={handleChange}
              placeholder="Profession"
              className="form-control"
              required="true"
            />
          </div>
          <button type="submit" className="btn btn-primary">Add Profile</button>

        </form>
        <div className="profile-container d-flex flex-wrap gap-4 ">
           {profiles.map((profile, index) => (
            <FormProfile
              key={index}
              userImage={profile.userImage}
              name={profile.name}
              email={profile.email}
              profession={profile.profession}
            />
          ))}
        </div>
      </div>
    </>
  );
}

export default App;

Result

Summary

This walkthrough demonstrates how to:

  1. Lift state up in the parent component.

  2. Pass props to child components.

  3. Use Bootstrap for responsive styling.

  4. Dynamically fetch and display image options from an external API.

  5. Manage forms and lists dynamically in React.

apiKey for fetching data from pexels api page ()

https://api.pexels.com/v1/search?query=nature&per_page=15
https://www.pexels.com/api/documentation/#photos-search
https://unsplash.com/documentation#search-photos