DEV Community

Cover image for Transforming a Static Web Page into a React Application
Afroza Nowshin
Afroza Nowshin

Posted on

Transforming a Static Web Page into a React Application

I used to be a front-end developer with a tool in my utility belt- React JS. Recently, I visited the path of front-end web development with a project that involved some interesting tasks. I thought of writing about the journey as a series of blog posts.

I was given a template with a bunch of HTML, CSS and JS files. From this template, I was required to build a website in React JS. The final output needs to be modular where some public API data can be displayed; even consumers' interaction with the website can be captured through form submission APIs.

My final project, in React, looks like this - https://scotts-totes.netlify.app/. Think of this website as the Dunder-Mifflin Infinity! The steps that I will be explaining today, and in later posts will help you turn any static HTML pages into a React app, with the integration of API data, React Routers, plugin JS files etc.

Here's how the template directory looks like usually:

template folder

From this project, we get the idea that our target website will have some pages such as - Home, About, Contact Us etc. Each of these pages are React Components. For simplicity, I created this project with React Class Components. You can try with later versions where you can use React Hooks.

Here are the steps for converting any HTML+CSS+JS template into a React app:

  1. Install Yarn, nvm (Node package manager) and use the latest node version
  2. Create a React app with CRA and create two folders "components" and "pages"
  3. Copy all the CSS, JS etc files into the public folder and insert all the necessary CSS and JS files inside the index.html of React app
  4. Create all the pages as React Class Components
  5. Create state objects in order to fetch and display API in your React pages
  6. Call any of the pages from App.js of your app.

Step-1:

I prefer Yarn for my Node package management because it takes less time than npm, and nvm for installing and managing multiple Node versions. For Yarn you need the latest version of Node. You can install Yarn from the official website. For nvm, follow its official git repo.

Step-2:

After this, build a React app from create-react-app boilerplate. I'm calling this project 'react-website', so the commands are:

npx create-react-app react-website
cd react-website
Enter fullscreen mode Exit fullscreen mode

You can start the server at localhost:3000 by writing the following in your terminal:

yarn start

Enter fullscreen mode Exit fullscreen mode

Your app directory should look like the following:

app directory

While I build a React project, I try to break down each page which is a component of its own, into multiple reusable components. Inside the src folder, create a folder named "components" where all the component files will remain, and a folder named "pages" where you will make every web page as components. In "react-website", we will have a home page, an about page, and a contact page. For all the pages, create three files namely "home.js", "about.js" and "contact.js".

Step-3

Your React app requires some resources such as CSS and plugin files, font folders, image folders etc. If you open public/index.html of your React app, you'll see that inside the HTML body, there is a div tag with the id "root". This is the file that gets served on the web when you build your React app for the deployment. As we used the CRA toolchain, the webpack is working under the hood, and all the necessary CSS, JS, images, font files, etc are bundled and turned into bundle.js. Therefore, you have to ensure that all the CDN links, CSS links, and JS links are integrated with this file, and that the resource files are inside the public folder.

Usually, the index.html file of a template includes CDN links and JS scripts. Open the index.html file of your given template folder, copy the tags between the head tags and paste it inside the head tags of public/index.html.
index file

Refer to the directory structure of a template folder that I mentioned earlier. Just copy all the resource or assets folders and paste them inside your public folder. Done!

resources copy

For all the pages that we will be using in our React apps, some extra steps are required for these various JS files. I will expound on this topic in a later post of this series.

Step-4

A bare minimum Home page as a Class Component looks like this:

import React, { Component } from "react";

class Home extends Component {

  render() {
    return (
      <div>
        <h1>That that I like that!</h1>
      </div>
    );
  }
}

export default Home;

Enter fullscreen mode Exit fullscreen mode

If you check all the HTML files of your template, you will see a lot of HTML codes with CSS which have built the structure of every page. Also, each of these files have the same links in their head tags and bottom of their body tags, have the navigation html repeated at each files as well as some of the codes for other segments of the website. What you have to do is:

  1. Change "class" into "className".
  2. Break down the repeated parts into JSX that your component will render.
  3. If there are comments in html, change the syntax into {/* comment */}

For large HTML files, use this website to achieve all these, and later paste inside your React Class Components.

Step-5

Let's show some public API data in this React app. Install axios and import in the home page.

yarn add axios

Enter fullscreen mode Exit fullscreen mode

I am using a free API that randomly generates activities that Regional Manager Michael Scott might do. Just kidding, but here’s the url . Axios takes care of the Promise API that is native to JS ES6. At first, we need to fetch the data when the component is in the DOM, so inside componentDidMount() write:

  componentDidMount() {

        axios.get("https://www.boredapi.com/api/activity")
            .then(response => {
                console.log(response.data)

            }).then(error => console.log(error))
    }
Enter fullscreen mode Exit fullscreen mode

We console logged the data. We want to render the activity inside our react component, here comes React States in handy. Inside the Class write:

constructor(props) {
  constructor(props) {
      super(props);

      this.state = {
            data: null,
        };     
Enter fullscreen mode Exit fullscreen mode

We have to update the state with our fetched data. While we are capturing the response inside componentDidMount, we need to do is:

this.setState({
      data: response.data.activity
  })

Enter fullscreen mode Exit fullscreen mode

Now, inside your rendered JSX, write the state data:

<div className="col-lg-2 col-md-3 col-sm-6 align-self-center">
  <div className="ltn__counterup-item-3 text-color-white">
       <h5>{this.state.data}</h5>
   </div>
 </div>

Enter fullscreen mode Exit fullscreen mode

You will be able to see random activities that Michael Scott is gonna do now. Here’s the full code:


class Home extends Component {
    constructor(props) {
        super(props);

        this.state = {
            data: null,
        };
    }

    componentDidMount() {

        axios.get("https://www.boredapi.com/api/activity")
            .then(response => {
                console.log(response.data)

                this.setState({
                    data: response.data.activity
                })
            })
    }

    render() {
        return (
            <>

                <div className="ltn__utilize-overlay"/>

                <div className="ltn__slider-area ltn__slider-3  section-bg-1">
                    <div className="ltn__slide-one-active slick-slide-arrow-1 slick-slide-dots-1">
                        <div className="ltn__slide-item ltn__slide-item-2 ltn__slide-item-3">
                            <div className="ltn__slide-item-inner">
                                <div className="container">
                                    <div className="row">
                                        <div className="col-lg-12 align-self-center">
                                            <div className="slide-item-info">
                                                <div className="slide-item-info-inner ltn__slide-animation">
                                                    <div className="slide-video mb-50">
                                                        <a
                                                            className="ltn__video-icon-2 ltn__video-icon-2-border"
                                                            href="https://www.youtube.com/embed/tlThdr3O5Qo"
                                                            data-rel="lightcase:myCollection"
                                                        >
                                                            <i className="fa fa-play"/>
                                                        </a>
                                                    </div>
                                                    <h1 className="slide-title animated ">
                                                        It is your birthday
                                                    </h1>
                                                    <h6 className="slide-sub-title animated">
                                                        {" "}
                                                        That's what she said
                                                    </h6>
                                                    <div className="btn-wrapper animated">

                                                        {/*<Link*/}
                                                        {/*  to="/about"*/}
                                                        {/*  className="btn btn-transparent btn-effect-3"*/}
                                                        {/*>*/}
                                                        {/*  LEARN MORE*/}
                                                        {/*</Link>*/}
                                                    </div>
                                                </div>
                                            </div>
                                            <div className="slide-item-img">
                                                <img src="img/service/21.jpg" alt="#"/>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div className="ltn__slide-item ltn__slide-item-2 ltn__slide-item-3">
                            <div className="ltn__slide-item-inner  text-right">
                                <div className="container">
                                    <div className="row">
                                        <div className="col-lg-12 align-self-center">
                                            <div className="slide-item-info">
                                                <div className="slide-item-info-inner ltn__slide-animation">

                                                    <div className="btn-wrapper animated">

                                                    </div>
                                                </div>
                                            </div>
                                            <div className="slide-item-img slide-img-left">
                                                <img src="img/service/21.jpg" alt="#"/>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>


                <div className="ltn__about-us-area pt-115 pb-95">
                    <div className="container">
                        <div className="row">
                            <div className="col-lg-7 align-self-center">
                                <div className="about-us-info-wrap">
                                    <div className="section-title-area ltn__section-title-2">
                                        <h6 className="section-subtitle ltn__secondary-color">
                                            About Us
                                        </h6>
                                        <h1 className="section-title">
                                            Your Satisfaction Is Our First Priority<span>.</span>
                                        </h1>

                                    </div>
                                    <div className="about-us-info-wrap-inner about-us-info-devide">

                                        <div className="list-item-with-icon">
                                            <ul>

                                                <li>
                                                    <a href="/">24/7 Online Support</a>
                                                </li>
                                                <li>
                                                    <a href="/">Easy To Use Apps</a>
                                                </li>
                                            </ul>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div className="col-lg-5 align-self-center">
                                <img src="img/logo.png" alt="Icon"/>
                            </div>
                        </div>
                    </div>
                </div>

                <div
                    className="ltn__counterup-area  bg-overlay-theme-black-80 pt-115 pb-70"
                    data-bg="img/bg/5.jpg"
                >
                    <div className="container">
                        <div className="row">
                            <div className="col-lg-4 col-md-12">
                                <div className="section-title-area ltn__section-title-2">
                                    <h6 className="section-subtitle white-color">activity</h6>
                                    <h1 className="section-title white-color">
                                        Hey Mister Scott Whatcha Gonna Do<span>.</span>
                                    </h1>
                                </div>
                            </div>

                            <div className="col-lg-2 col-md-3 col-sm-6 align-self-center">
                                <div className="ltn__counterup-item-3 text-color-white">
                                    <h5>{this.state.data}
                                    </h5>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

            </>
        );
    }
}

export default Home;

Enter fullscreen mode Exit fullscreen mode

Step-6

Import home page and call it from App.js

import React, { Component } from "react";
import "./App.css";
import Home from "./pages/home";

class App extends Component {
  render() {
    return (
      <div className="body-wrapper">
      <Home/>
      </div>
    );
  }
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Whenever you insert a component in the App.js, only that page component is mounted in the DOM. For navigating all the pages, we will be needing a navbar which will be mobile responsive. In the following post, I will write about how you can add all sorts of navigation systems to this React app.

Find the code here - https://github.com/Afroza2/ReactforReal-Turning-into-React-app/tree/master

Discussion (0)