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

Step-by-Step Procedure to Implement React Form Profile App
1. Setting Up the Project
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
Install Bootstrap CSS: Install Bootstrap using npm:
npm install bootstrap
Import Bootstrap in the
main.jsx
file:import 'bootstrap/dist/css/bootstrap.min.css';
Setup Folder Structure: Create a
components
folder inside thesrc
directory:src/ |-- components/ |-- FormProfile.jsx |-- AppFormProfile.jsx
2. Implement the Parent Component: AppFormProfile.jsx
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
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:
Lift state up in the parent component.
Pass props to child components.
Use Bootstrap for responsive styling.
Manage forms and lists dynamically in React.
Challenge : Update the component to fetch image URLs from Unsplash and allow the user to select one.
apiKey for fetching data from pexels api page (https://api.pexels.com/v1/search?query=nature&per_page=15)
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
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
Result
Summary
This walkthrough demonstrates how to:
Lift state up in the parent component.
Pass props to child components.
Use Bootstrap for responsive styling.
Dynamically fetch and display image options from an external API.
Manage forms and lists dynamically in React.
Last updated