React Lecture 3: Forms, Conditional Content, and State Management - MantsSk/CA_PTUA14 GitHub Wiki
In this lecture, you will build on your knowledge from Lectures 1 and 2 by adding dynamic functionality to your news website. Specifically, you will learn how to:
- Design Reusable Components: Create a general-purpose modal that can wrap any content.
- Build Controlled Forms: Use state to capture and manage user input.
- Implement Conditional Rendering: Show or hide content based on user interactions.
- Practice State Management: Update complex component state, such as dynamically adding new articles.
A well-designed modal should be reusable across your project. We achieve this by creating a component that:
- Accepts a
show
prop to determine visibility. - Uses the
children
prop to render arbitrary content. - Provides an
onClose
callback to signal when it should be hidden.
import React from 'react';
import './Modal.css';
function Modal({ show, onClose, children }) {
if (!show) return null;
return (
<div className="modal-overlay">
<div className="modal">
<button className="close-button" onClick={onClose}>X</button>
{children}
</div>
</div>
);
}
export default Modal;
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal {
background: #fff;
padding: 30px;
border-radius: 8px;
width: 90%;
max-width: 500px;
}
.close-button {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
-
Conditional Rendering: The
if (!show) return null;
statement prevents the modal from rendering when it’s not needed, keeping the DOM clean. -
Reusability via
children
: By wrapping the modal’s content in{children}
, this component can be used to display any type of content—not just forms. -
Event Propagation: The close button triggers
onClose
so that the parent component can manage the modal’s visibility state.
The New Article form is a controlled form component that gathers user input for new articles. It demonstrates key concepts like input handling, form submission, and state reset.
import React, { useState } from 'react';
function NewArticleForm({ onSubmit }) {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
onSubmit({ title, content });
setTitle("");
setContent("");
};
return (
<form onSubmit={handleSubmit}>
<h2>Create New Article</h2>
<div className="form-group">
<label htmlFor="title">Title:</label>
<input
id="title"
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
/>
</div>
<div className="form-group">
<label htmlFor="content">Content:</label>
<textarea
id="content"
value={content}
onChange={(e) => setContent(e.target.value)}
required
/>
</div>
<button type="submit">Add Article</button>
</form>
);
}
export default NewArticleForm;
import React, { useState } from 'react';
import Article from './Article';
import Modal from './Modal';
import NewArticleForm from './NewArticleForm';
import './ArticleList.css';
function ArticleList() {
const [articles, setArticles] = useState([
{ title: "React 101: Getting Started", content: "Learn the basics of React, a powerful UI library." },
{ title: "Understanding JSX", content: "JSX is a syntax extension for JavaScript that allows writing HTML in React." },
{ title: "Component Reusability in React", content: "Building modular components improves scalability and maintainability." }
]);
const [showModal, setShowModal] = useState(false);
const handleAddArticle = (newArticle) => {
setArticles(prevArticles => [...prevArticles, newArticle]);
setShowModal(false);
};
return (
<div className="article-list-container">
<button onClick={() => setShowModal(true)}>Add New Article</button>
<Modal show={showModal} onClose={() => setShowModal(false)}>
<NewArticleForm onSubmit={handleAddArticle} />
</Modal>
<div className="article-list">
{articles.map((article, index) => (
<Article key={index} title={article.title} content={article.content} />
))}
</div>
</div>
);
}
export default ArticleList;
This CSS could be spread out among components you already created.
/* ArticleFormList.css */
/* Container for the article list and form */
.article-list-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
/* Button to add a new article */
.article-list-container button {
background-color: #3498db;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin-bottom: 20px;
font-size: 16px;
}
.article-list-container button:hover {
background-color: #2980b9;
}
/* Styling for the list of articles */
.article-list {
display: flex;
flex-direction: column;
gap: 20px;
}
/* Individual article item */
.article {
background: #fff;
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Form styling */
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
.form-group textarea {
resize: vertical;
}
/* Submit button styling */
button[type="submit"] {
background-color: #27ae60;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
button[type="submit"]:hover {
background-color: #219150;
}
Component Reusability: You built a general-purpose Modal component that can be used to wrap any content, emphasizing component reusability and separation of concerns.
Controlled Forms: By managing form input through state, you learned how to capture, validate, and submit user data in a predictable manner.
Conditional Rendering: You practiced showing and hiding UI elements based on state, which is critical for creating dynamic, responsive applications.
State Management with useState: You enhanced your application’s interactivity by managing multiple state values—from toggling modals to updating lists—demonstrating the power of React’s state management.
Improve your application according to what we did in lecture
Introduce a smooth fade-in/fade-out effect when the modal opens or closes.
Modify the existing Modal.jsx and Modal.css files.
Add CSS transitions to animate the modal’s appearance and disappearance.
Ensure that the component still respects the show prop for conditional rendering.
Use conditional rendering to enhance user feedback.
In ArticleList.jsx, check the length of the articles array.
If no articles exist, display a message such as “No articles available. Please add a new article.”
Otherwise, display the list of articles as usual.
Allow users to edit articles already added to the list.