Welcome to frontend development! In this guide, you'll learn how to set up a basic React environment from scratch, implement state management using the Context API, and integrate API calls to fetch data dynamically. Whether you're new to React or looking to deepen your understanding, this guide will walk you through the process step by step.
By the end, you'll have a flexible, functional frontend that can fetch data from any API and handle state efficiently. Let's dive in!
While Create-React-App (CRA) is a great tool for quickly bootstrapping React applications, it comes with pre-built configurations and dependencies that you might not need. Building a project from scratch using Webpack and Babel provides deeper insights into the build process and gives you more flexibility.
Starting with a "vanilla" React setup allows you full control over the build process, providing valuable insights into the tools you're working with. You'll learn how Webpack, Babel, and React work together to create dynamic interfaces.
React was created by Facebook in 2013 to address the growing complexity of web applications. It allows developers to build interactive user interfaces efficiently by breaking the UI into reusable components. React also introduced the concept of a "virtual DOM," which optimizes updates to the real DOM by only re-rendering the components that have changed. Today, React is one of the most popular JavaScript libraries and is widely used by companies like Facebook, Instagram, Netflix, and Airbnb.
Initialize your project by running the following command in your project directory:
npm init
Install the necessary dependencies:
npm install react react-dom
Install build tools like Webpack and Babel:
npm install webpack webpack-cli webpack-dev-server --save-dev npm install @babel/core @babel/preset-env @babel/preset-react babel-loader --save-dev npm install css-loader style-loader
Add a start script to your package.json
:
"scripts": { "start:dev": "webpack serve --config ./webpack.config.js --mode development" }
Next, we will configure Webpack to bundle our JavaScript, CSS, and other assets.
Webpack is a module bundler introduced in 2012 by Tobias Koppers. In modern JavaScript development, we often break down our code into smaller modules or files. Webpack takes all of these files and bundles them into a single output file (or multiple files if needed) so that they can be efficiently loaded by a browser. It also provides additional features like code splitting, hot module replacement (HMR), and asset management.
Create a webpack.config.js
file in the root of your project:
const path = require('path'); module.exports = { context: __dirname, entry: path.resolve(__dirname, './src/index.js'), output: { path: path.resolve(__dirname, './public'), filename: 'bundle.js', }, devServer: { static: path.resolve(__dirname, './public'), }, module: { rules: [ { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/env', '@babel/react'], }, }, }, { test: /\.css$/, use: ['style-loader', 'css-loader'], }, ], }, resolve: { extensions: ['.js', '.jsx', '*'], }, };
Create an index.html
file in the public
directory. This will serve as the entry point for the React app:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>React App</title> </head> <body> <div id="root"></div> <script src="bundle.js"></script> </body> </html>
Run the dev server:
npm run start:dev
Now you should have your Webpack development server running, and any changes will automatically reload the page!
Now, let’s build a simple React component to display some data and introduce API fetching in the next steps.
Create an App.js
component:
// /src/components/App.js import React from 'react'; export const App = () => { return ( <div className="App"> <h1>{'App! Now with 100% more React'}</h1> </div> ); };
Modify index.js
to render the App
component:
// /src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import { App } from './components/App'; ReactDOM.render(<App />, document.getElementById('root'));
At this point, you should see "Welcome to Your React App" displayed in the browser.
We'll now implement the Context API for global state management, allowing different components to share and update the same state.
React's Context API was introduced in version 16.3 (2018) as a simple way to manage global state without having to rely on external state management libraries like Redux. It's now a built-in solution for managing application-wide state, providing an easy way to share data across components without the need for "prop drilling" (passing props down multiple levels).
Create a context
directory and inside it, create a new file AppContext.js
:
// /src/context/AppContext.js import React, { createContext, useState } from 'react'; export const AppContext = createContext(); export const AppProvider = ({ children }) => { const [state, setState] = useState({ data: [], loading: true, error: null, }); const updateData = (newData) => { setState({ ...state, data: newData, loading: false }); }; return ( <AppContext.Provider value={{ state, updateData }}> {children} </AppContext.Provider> ); };
Wrap your app in the AppProvider
in index.js
:
// /src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import { App } from './components/App'; import { AppProvider } from './context/AppContext'; ReactDOM.render( <AppProvider> <App /> </AppProvider>, document.getElementById('root') );
Now, your application is ready to manage state globally across components using the Context API!
Let’s modify the App
component to fetch data from an external API and render it. We'll also manage the state using the Context API.
App.js
to Fetch DataUpdate the App
component to fetch data from an API and store it in context:
// /src/components/App.js import React, { useContext, useEffect } from 'react'; import { AppContext } from '../context/AppContext'; export const App = () => { const { state, updateData } = useContext(AppContext); useEffect(() => { const fetchData = async () => { try { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); const data = await response.json(); updateData(data); // Update the state with fetched data } catch (error) { console.error('Error fetching data:', error); } }; fetchData(); }, [updateData]); if (state.loading) { return <div>Loading...</div>; } return ( <div className="App"> <h1>Data from API</h1> <ul> {state.data.map((item) => ( <li key={item.id}>{item.title}</li> ))} </ul> </div> ); };
Now, the app will fetch posts from the API and render the titles in a list.
Here’s a summary of the file structure:
/public
- index.html
/src
/components
- App.js
/context
- AppContext.js
- index.js
- webpack.config.js
/package.json
Run the dev server again with:
npm run start:dev
You should see the list of API data rendered on the page, complete with state management via the Context API!
With this setup, you now have a powerful foundation for building scalable, dynamic, and data-driven frontend applications using React, Webpack, and the Context API. You’ve also learned how to integrate API data fetching, making your app truly dynamic and capable of interacting with real-world data.
Now that you have a robust frontend setup with React, Webpack, and state management using the Context API, you're ready to scale your project. Here are a few next steps:
Happy Hacking!