Build a web app with React, an open source framework
Introduction
React has quickly become one of the most popular open source frameworks for building user interfaces and web applications. Maintained by Facebook and backed by a thriving community of developers, React makes it easy to manage state and build complex, interactive UIs from simple, reusable components.
Some key benefits of React include:
- Component architecture - React structures UI code into self-contained, modular components that can be composed together. This promotes separation of concerns and reusability. For example, a Button component can be reused across the app.
- Virtual DOM - React uses a virtual representation of the real DOM and intelligently updates it when state changes, avoiding costly DOM manipulations. This improves performance significantly for complex UIs.
- Managing state - React's unidirectional data flow and use of state hook make managing UI state simple and declarative. Local component state is easy to reason about.
In this tutorial, we'll build a simple web app to demonstrate core React concepts like components, props, state, and hooks for complete beginners. We'll assume you have basic knowledge of HTML, CSS, and JavaScript but may be new to React.
By the end, you'll have a solid foundation for building production-ready React apps and be ready to tackle more advanced features like routing, data fetching, and tooling. Let's get started!
Setting Up a React Project
Before we can start building with React, we need to set up a development environment and build process for our app. The fastest way to get started is using Create React App.
Create React App handles all the complex configuration needed for React projects - Webpack, Babel, ESLint, etc. To set it up:
npx create-react-app my-app
cd my-app
npm start
This scaffolds a project with an optimized production-ready build, dev server, and other tools needed to kickstart development.
Alternative setup options include Next.js, Gatsby, or configuring Webpack manually. But Create React App works well for learning and simple projects.
We'll also initialize a Git repository to enable version control for our app:
git init
And create a .gitignore
file to exclude files like node_modules
.
Project Structure Overview
The Create React App folder structure includes:
src
- Contains our React codepublic
- Static assets likeindex.html
package.json
- Defines dependencies and scriptsnode_modules
- Downloaded dependencies
src/index.js
renders the root App component into the DOM. src/App.js
will be the root component for our app.
Component relationship diagram
Dependencies Overview
Key dependencies created include:
- React - Main React library
- ReactDOM - Used to render components to DOM
- Babel - Transpiles modern JavaScript
- Webpack - Bundles app and assets for production
These are all preconfigured and hidden away in Create React App. Additional libraries can be added later as needed.
Building React Components
React apps are built using components - reusable, modular pieces of UI code.
Components can be defined as functions or classes:
// Function component
function Header() {
return <h1>My Website</h1>;
}
// Class component
class Header extends React.Component {
render() {
return <h1>My Website</h1>;
}
}
All components must have a render()
method returning JSX markup to render.
JSX Syntax
JSX allows writing HTML-like syntax in React:
const element = <h1 className="header">Hello World</h1>;
It compiles to regular JavaScript but provides a templating mechanism for React components.
Note differences like using className
instead of class
for adding CSS classes.
Component Composition
Components can render other components, allowing complex UIs to be built from simple building blocks:
function App() {
return (
<div>
<Header />
<Content />
</div>
);
}
function Header() {
return <h1>My Website</h1>;
}
function Content() {
return <p>This is the content</p>;
}
Data gets passed between components using props
:
<Header title="My Website"/>
Props can be destructured right in the function parameters:
function Header({ title }) {
return <h1>{title}</h1>;
}
This composition is a key advantage of React.
Managing State with Hooks
State allows components to manage data that determine rendering.
React provides special functions called hooks for state and other features. The useState
hook initializes state:
import { useState } from 'react';
function App() {
const [count, setCount] = useState(0); // Initialize with 0
return (
// Omitted
);
}
useState
returns the current state value and a function to update it. We can call setCount
to change the count
state variable.
Other useful builtin hooks include useEffect
, useRef
, useContext
, etc.
Handling Events
We can handle user events like clicks by attaching event handlers:
function App() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(prevCount => prevCount + 1); // Update state
}
return (
<button onClick={handleClick}> // Attach handler
Click
</button>
);
}
Event handlers can also be passed between components via props:
<Button onClick={handleClick} />
This allows component reuse and separation of concerns.
Updating the UI
When state is updated with setCount
, React re-renders the component with the new state value.
This happens in two phases:
- Render - Components rerender with updated state
- Commit - Changes are applied to DOM
So updating count
will show the new value:
<p>You clicked {count} times</p>
React handles updating the DOM efficiently using its virtual representation.
Styling and CSS
There are several ways to style React apps:
- Import CSS files -
import './styles.css'
- CSS Modules - For scoped component styles
- Inline styles - With JavaScript object literals
- CSS-in-JS - Libraries like Styled Components
A best practice is to keep component code separate from styles.
Global Styles
Global styles affect the entire app. They can be defined in src/index.css
and imported in src/index.js
:
/* index.css */
body {
margin: 0;
font-family: sans-serif;
}
/* Index.js */
import './index.css'; // Imports global styles
Global styles are loaded at the root before components.
Scoped Styles
For component-specific styles, CSS Modules or styled-components can scope CSS to each component.
This avoids global side effects but requires more setup:
// App.module.css
.title {
/* Scoped to App */
}
// App.js
import styles from './App.module.css';
function App() {
return <h1 className={styles.title}>Hello World</h1>;
}
Overall, keeping components self-contained with scoped CSS is preferred for modularity.
Data Fetching
Components often need to fetch data from an API endpoint.
The useEffect
hook runs code after render, allowing data fetching:
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => {
setPosts(data);
})
}, []); // Empty array = run once on mount
Here we fetch posts from a sample API and save them to state on mount.
useEffect
unifies lifecycle methods like componentDidMount
into one API.
It runs after render allowing interaction with rendered DOM elements.
useEffect
useEffect
accepts a callback function that runs after render:
useEffect(() => {
// Run after render
});
The second argument controls when it runs:
[]
- Only on mount- No array - On every render
[count]
- Whencount
changes
This allows flexible synchronization of effects.
Component Lifecycle
Class components had separate lifecycle methods like componentDidMount
.
useEffect
unifies these into a single API:
componentDidMount
-useEffect(() => {}, [])
componentDidUpdate
-useEffect(() => {})
componentWillUnmount
- Return cleanup function
So we can fetch data on mount with:
useEffect(() => {
// Fetch data
}, []);
Routing and Navigation
For multi-page apps, React Router manages routing:
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
Routes are declared and matched based on path. Nested routes, parameters, and more are supported.
Linking Between Pages
The <Link>
component renders a link for declarative navigation between pages:
<Link to="/about">About</Link>
Styling the active link is easy:
<Link to="/about" className={({ isActive }) => (isActive ? 'active' : '')}>
This avoids imperatively pushing routes.
Lazy Loading
To load bundles on demand, components can be lazily loaded with React.lazy
and Suspense
:
const Home = React.lazy(() => import('./Home'));
function App() {
return (
<Suspense fallback={<Loader />}>
<Home />
</Suspense>
);
}
This helps improve initial load time. Caveats include shared dependencies.
Deployment and Hosting
To share a React app, we need to deploy it. Let's look at build process and hosting options.
The project can be built for production using:
npm run build
This optimizes the output in build/
for deployment.
Build Process
npm run build
:
- Minifies and transpiles ES6+ to ES5
- Inlines CSS, optimizes images
- Replaces development variables
- Generates production-ready build
All configuration is handled by Create React App's Webpack setup.
Deployment Options
There are many hosting options for React apps:
- Static site hosting - Vercel, Netlify, GitHub Pages
- Traditional servers - Node.js, Nginx
- Serverless - AWS Lambda, Azure Functions
Free services like Vercel and Netlify simplify deployment with continuous integration and deployment.
For server-side rendering, a Node.js server is required.
Conclusion and Next Steps
We covered a lot of ground introducing React concepts like components, props, state, JSX, hooks, routing, and deployment options.
React's component model and virtual DOM make it ideal for building complex, reactive user interfaces. There is a thriving ecosystem of libraries like React Router and Styled Components that enhance its capabilities.
Some areas for further learning include advanced state management with Redux or MobX, unit testing, form handling, performance optimization, and integrating React with backend frameworks like Node.js and Django.
React Native also allows building mobile apps with React. Overall, React is an excellent open source framework for crafting modern web applications.
To recap, we:
- Set up a React dev environment
- Built components and used JSX
- Managed state with hooks like useState
- Added styles, fetched data, handled routing
- Looked at build process and deployment options
You should now have the foundation to start building your own React apps! The DevHunt community is also a great place to find and promote new open source libraries and frameworks like React to enhance your development workflow.