https://github.com/arnobt78/paragraph-generator--react-fundamental-project-8
A modern, interactive React application that generates a customizable number of random paragraphs ("Lorem Ipsum") for use in design, development, and content prototyping. This project demonstrates fundamental React concepts, state management, and functional component design with practical, real-world utility
https://github.com/arnobt78/paragraph-generator--react-fundamental-project-8
controlled-input educational-project functional-components javascript list-rendering lorem-ipsum lorem-ipsum-generator nanoid paragraph-generator random-text random-text-generator react react-basics react-components react-dom react-fundamentals react-hooks react-learning react-tutorial vite
Last synced: 28 days ago
JSON representation
A modern, interactive React application that generates a customizable number of random paragraphs ("Lorem Ipsum") for use in design, development, and content prototyping. This project demonstrates fundamental React concepts, state management, and functional component design with practical, real-world utility
- Host: GitHub
- URL: https://github.com/arnobt78/paragraph-generator--react-fundamental-project-8
- Owner: arnobt78
- License: other
- Created: 2025-02-09T08:56:43.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2026-03-11T14:05:18.000Z (3 months ago)
- Last Synced: 2026-03-11T19:55:01.477Z (3 months ago)
- Topics: controlled-input, educational-project, functional-components, javascript, list-rendering, lorem-ipsum, lorem-ipsum-generator, nanoid, paragraph-generator, random-text, random-text-generator, react, react-basics, react-components, react-dom, react-fundamentals, react-hooks, react-learning, react-tutorial, vite
- Language: CSS
- Homepage: https://create-paragraph.vercel.app/
- Size: 118 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Paragraph Generator – React, Vite, JavaScript, Custom CSS Fundamental Project 8
A modern, interactive React application that generates a customizable number of random paragraphs ("Lorem Ipsum") for use in design, development, and content prototyping. This project demonstrates fundamental React concepts, state management, and functional component design with practical, real-world utility.
[](https://opensource.org/licenses/MIT)
[](https://react.dev/)
[](https://vitejs.dev/)
[](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
- **Live Demo:** [https://create-paragraph.vercel.app/](https://create-paragraph.vercel.app/)

## Table of Contents
- [Project Summary](#project-summary)
- [Features](#features)
- [Technology Stack](#technology-stack)
- [Project Structure](#project-structure)
- [Component Overview](#component-overview)
- [How It Works (Walkthrough)](#how-it-works-walkthrough)
- [Setup & Usage](#setup--usage)
- [Environment Variables (.env)](#environment-variables-env)
- [Key Concepts & Teaching Content](#key-concepts--teaching-content)
- [Reusing Components in Other Projects](#reusing-components-in-other-projects)
- [API, Backend & Routes](#api-backend--routes)
- [Customization](#customization)
- [Keywords](#keywords)
- [Conclusion](#conclusion)
- [License](#license)
---
## Project Summary
The **Paragraph Generator** is a learning-focused React project that lets users generate a desired number of random placeholder paragraphs (1–8) with a single form submit. It showcases **form handling**, **state management** (`useState`), and **dynamic list rendering** in React, making it a solid resource for beginners and anyone looking for a clear example of React fundamentals.
The UI is minimal and accessible: users enter a number between 1 and 8, click **Generate**, and the app instantly displays that many paragraphs below the form. There is no backend or API—all data lives in the frontend, so the project is ideal for studying React in isolation.
---
## Features
- **Custom paragraph count:** Choose how many paragraphs to show (1–8).
- **Form handling:** Number input with `min`/`max` validation and controlled component pattern.
- **Live preview:** Generated paragraphs appear immediately on submit.
- **Stable list keys:** Uses `nanoid` for unique keys in `.map()` to satisfy React’s reconciliation and avoid key warnings.
- **Accessible UI:** Semantic HTML (``, ``, ``, ``) and associated form controls.
- **Fast tooling:** Vite for quick dev server and optimized production builds.
- **Lint:** ESLint with React and React Hooks rules; run with `npm run lint`.
---
## Technology Stack
| Technology | Purpose |
| --------------------- | ------------------------------------------------- |
| **React 18** | UI library; functional components and hooks |
| **Vite 4** | Dev server, HMR, and production bundling |
| **JavaScript (ES6+)** | No TypeScript; modern syntax and modules |
| **nanoid** | Small library for unique IDs (list keys) |
| **CSS** | Custom global and component styles; CSS variables |
| **HTML5** | Single `index.html` as app shell |
---
## Project Structure
```bash
08-lorem-ipsum/
├── public/
│ └── vite.svg # Favicon / static asset
├── src/
│ ├── App.jsx # Main component: form + paragraph list
│ ├── data.js # Array of 8 paragraph strings (data source)
│ ├── index.css # Global + project-specific CSS
│ └── main.jsx # React entry: mounts app into #root
├── index.html # HTML template and SEO meta tags
├── vite.config.js # Vite config (React plugin)
├── eslint.config.js # ESLint flat config (React + Hooks)
├── package.json
└── README.md
```
- **Entry:** `index.html` loads `src/main.jsx`, which renders `` into `#root`.
- **Data:** `src/data.js` exports one array; no backend or API.
- **Styling:** `src/index.css` is imported in `main.jsx` and applies globally.
---
## Component Overview
### `main.jsx` (Entry)
- Imports React, ReactDOM, `App`, and `index.css`.
- Uses `createRoot` and `render` to mount `` inside `
`.
- Wraps the app in `` for development checks.
```jsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";
ReactDOM.createRoot(document.getElementById("root")).render(
,
);
```
---
### `App.jsx` (Main UI)
- **State:** `count` (number of paragraphs to show, default `1`), `text` (array of paragraph strings to render).
- **Form:** Number input (min 1, max 8), label, and submit button. On submit, `handleSubmit` reads the value, parses it, slices `data` to that length, and updates `text`.
- **Output:** Renders an `` that maps over `text` and shows each item in a `
` with a `nanoid()` key.
Relevant snippets:
```jsx
const [count, setCount] = useState(1);
const [text, setText] = useState([]);
const handleSubmit = (e) => {
e.preventDefault();
let amount = parseInt(count);
setText(data.slice(0, amount));
};
```
```jsx
{text.map((item) => {
return
{item}
;
})}
```
---
### `data.js` (Data Module)
- Exports a single array of 8 strings. Each string is one paragraph (various placeholder themes: candy, zombie, cat, cheese, etc.).
- Used only by `App.jsx` via `data.slice(0, amount)` to select how many paragraphs to display.
---
### `index.css` (Styles)
- **Global:** Reset (margin/padding/box-sizing), `:root` variables (colors, spacing, shadows, typography), base styles for `body`, headings, buttons, forms, alerts.
- **Project-specific:** `.section-center`, `.lorem-form`, `.lorem-text` for layout and appearance of the generator UI.
- Reusable utility classes (e.g. `.btn`, `.alert`, `.form`) can be reused in other pages or components.
---
## How It Works (Walkthrough)
1. **Page load:** `main.jsx` mounts `App`. Initial state: `count = 1`, `text = []`, so no paragraphs are shown yet.
2. **User input:** User changes the number input (1–8). Because the input is controlled (`value={count}`, `onChange` updating `count`), React re-renders with the new value.
3. **Submit:** User clicks **Generate**. `handleSubmit` runs: `e.preventDefault()` stops full page submit; `amount = parseInt(count)`; `setText(data.slice(0, amount))` sets state to the first `amount` items from `data`.
4. **Re-render:** React re-renders `App`. The `.map()` over `text` produces one `
` per paragraph, each with a unique `key={nanoid()}`.
5. **Result:** The requested number of paragraphs appears below the form. Changing the number and clicking **Generate** again updates the list.
No server, no API, no routing—everything happens in the browser with React state and the static `data` array.
---
## Setup & Usage
### Prerequisites
- **Node.js** (v14 or higher recommended)
- **npm** (or yarn/pnpm)
### Installation
1. **Clone the repository**
```sh
git clone https://github.com/arnobt78/Paragraph-Generator--React-Fundamental-Project-8.git
cd Paragraph-Generator--React-Fundamental-Project-8
```
2. **Install dependencies**
```sh
npm install
```
### Run locally
```sh
npm run dev
```
Then open the URL shown in the terminal (typically `http://localhost:5173`). Use the form to pick a number (1–8) and click **Generate** to see the paragraphs.
### Build for production
```sh
npm run build
```
Output goes to the `dist/` folder. To preview the production build locally:
```sh
npm run preview
```
### Lint
```sh
npm run lint
```
Runs ESLint on `src` (and any other configured paths). Fix any reported errors or warnings to keep the codebase consistent.
---
## Environment Variables (.env)
This project **does not use any environment variables**. All behavior is driven by the code and the static `data.js` file. There is no API key, no backend URL, and no feature flags.
- The repo’s `.gitignore` already includes `.env` so that if you add a `.env` file later (e.g. for an optional API or analytics), it won’t be committed.
- **If you extend the project** (e.g. add an API or analytics):
- Create a `.env` file in the project root.
- In Vite, use `import.meta.env.VITE_*` for variables you want in the client (e.g. `VITE_API_URL`).
- Add `.env.example` with placeholder names (no secrets) and document each variable in the README.
For this educational version, **no `.env` file or environment variables are required** to run or build the app.
---
## Key Concepts & Teaching Content
### 1. `useState` Hook
State is stored and updated with `useState`. When the setter is called, React re-renders the component and any children that depend on that state.
```js
const [count, setCount] = useState(1); // number of paragraphs
const [text, setText] = useState([]); // array of strings to show
```
### 2. Controlled Input
The number input is “controlled”: its value is `count` and changes go through `setCount`, so React always owns the value.
```jsx
setCount(e.target.value)}
min="1"
max="8"
/>
```
### 3. Form Submit Handler
Prevent default form submission and derive the amount from state (or from the event target if you prefer), then update state.
```js
const handleSubmit = (e) => {
e.preventDefault();
let amount = parseInt(count);
setText(data.slice(0, amount));
};
```
### 4. Slicing an Array
`Array.prototype.slice(0, n)` returns the first `n` elements without mutating the original array—ideal for “first N paragraphs.”
```js
setText(data.slice(0, amount));
```
### 5. List Rendering and Keys
When rendering lists, each item must have a stable, unique `key` so React can reconcile efficiently. Here, `nanoid()` generates a new ID per item.
```jsx
{
text.map((item) =>
{item}
);
}
```
### 6. Single Source of Truth
Paragraph content lives only in `data.js`. The UI only decides _how many_ to show; it doesn’t duplicate or modify the original data.
---
## Reusing Components in Other Projects
### Reusing the “paragraph generator” behavior
1. **Copy `App.jsx`** (and optionally rename it, e.g. `ParagraphGenerator.jsx`). Keep the same logic: `useState` for count and text, form with number input, `handleSubmit` that does `data.slice(0, amount)`, and the `.map()` over `text`.
2. **Copy or adapt `data.js`**—either the same array or your own list of strings.
3. **Install `nanoid`** in the other project: `npm install nanoid`.
4. **Styling:** Copy the relevant parts of `index.css` (e.g. `.section-center`, `.lorem-form`, `.lorem-text`, and any variables/buttons you use), or replace with your own CSS/styled-components.
### Reusing only the form pattern
- Use the same controlled input + `handleSubmit` pattern with your own state and logic (e.g. different limits, different data source, or fetching from an API instead of `data.js`).
### Reusing only the data
- Import `data` from `data.js` (or a copy) in any component that needs placeholder text—e.g. for a preview, a modal, or a different layout.
---
## API, Backend & Routes
- **API:** None. The app does not call any external or internal API. All text comes from the in-memory `data` array.
- **Backend:** None. The project is frontend-only. Deployment is typically static (e.g. Vercel, Netlify) serving the built `dist/` output.
- **Routes:** Single page. There is no router (no React Router or similar). One URL, one screen: the paragraph generator form and result.
---
## Customization
- **Paragraph content:** Edit `src/data.js` to add, remove, or change the strings. Adjust the `max` on the input in `App.jsx` if you add more than 8.
- **Paragraph limits:** In `App.jsx`, change the input’s `min` and `max` (and optionally the initial `useState(1)` default) to allow a different range (e.g. 1–20).
- **Styling:** Change `src/index.css`—especially `:root` variables and the `.section-center`, `.lorem-form`, `.lorem-text` rules—to match your theme or layout.
- **Copy and headings:** Change the `
` and button/label text in `App.jsx` to fit your branding or language.
---
## Keywords
React, Paragraph Generator, Lorem Ipsum, Vite, useState, nanoid, JavaScript, Functional Components, Form Handling, Array.slice, Random Text, Placeholder Text, Frontend, CSS, Web App, Beginner Project, Controlled Input, List Rendering, React Hooks, ESLint
---
## Conclusion
This **Paragraph Generator** project is a small, self-contained example of React fundamentals: state, controlled inputs, form handling, and list rendering with stable keys. It has no backend or environment variables, so you can run and modify it immediately. Use it to learn React, to share with others, or as a starting point for a more advanced app (e.g. with an API, routing, or more complex UI).
---
## License
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT). Feel free to use, modify, and distribute the code as per the terms of the license.
---
## Happy Coding! 🎉
This is an **open-source project** — feel free to use, enhance, and extend this project further!
If you have any questions or want to share your work, reach out via GitHub or my portfolio at [https://www.arnobmahmud.com](https://www.arnobmahmud.com).
**Enjoy building and learning!** 🚀
Thank you! 😊