React.js for the Visual Learner (Chapter 7 | Building Our First User Interface)

Prerequisites

Read Chapter 1 | What is This All About?
Read Chapter 2 | What is React and Why is it Cool?
Read Chapter 3 | Building Our Houses
Read Chapter 4 | Our First Village
Read Chapter 5 | Additions to Our Houses
Read Chapter 6 | Building Our First Project

Get the Official Ebook

If you want to support me, you can go here to get an official copy of this ebook via PDF, MOBI, and EPUB.

Code Collection

Through Chapter 5: http://bit.ly/2qRNkQX
Chapter 6+: https://github.com/michaelmang/React-for-the-Visual-Learner

Breaking Down the Mockup

The previous chapter was a lot of setup and I know you are eager to dive into creating a user interface. So, let’s jump right into it!

In this chapter, we are creating a landing page for our user interface. Personally, I am sort of a hybrid between a designer and developer which allows me to create complete mockups with vector graphics as well as the implementation of it with code.

Because of that, I would love to go through the entire process of creating a mockup for a landing page. However, for the sake of time and getting the hand of a more of a real-world application (since most jobs won’t allow you to wear too many hats), we are just going to work from a preexisting mockup that I have created:

Let’s get in the mindset that this is a mockup created by a designer that we work with. They handed it to us and we were told to implement in with React.

What do we do first?

As we did with our Koala, we must start by breaking this landing page down into our component hierarchy as specified by The React Village Design.

Village

A village is a complete view of a user interface. View can be thought of as what you would normally associate as an entire page in more traditional web applications. Because we are making a single page application, we distinguish our terminology and call the current “page” that is toggled on as the view/village.

In our project, the entire landing page is the village. We can create a village component called LandingPage.

Neighborhoods

The next level down on the component hierarchy of the village design is neighborhoods.

Neighborhoods in a user interface are collections of blocks that work together to form a complete section of the view.

In our project we have the following neighborhoods (sections):

Header

Section A

Section B

Section C

Footer

Blocks

Next, we go down one more level in the component hierarchy in terms of the village design, blocks.

Blocks in a user interface are collections of houses that work together to form a specific functionality/purpose to the view.

In our project, we have the following blocks:

Navigation

Call to Action

Section Description

Houses

Finally, we have houses. Houses are the basic building blocks of a user interface. Some of our houses will be combined into a block (multiple components that form one functionality/purpose) and other houses will stand-alone (one component that is not working with other components to form one functionality/purpose). Let’s look at all of our houses and distinguish between those that will be combined in blocks and those that will stand-alone:

Houses in Blocks


Navigation Block

Branding

Demo Link

Call to Action Block

Title

Subtitle

Button

Section Description Block

Heading

Paragraph

Divider


Stand-Alone Houses

Slack Channel

Laptop

Article Cover

These houses will stand-alone because they aren’t being combined to form any blocks. Therefore, they can be nested right under the neighborhoods (sections) to which they belong.

Putting It All Together

Cool! We’ve been able to break down our landing page into proper component hierarchy. Let’s put all of these together so we understand how the nesting will work:

- App
  - Landing Page (Village)
    - Header (Neighborhood)
- Navigation (Block)
- Branding (House)
- Demo Link (House)
- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)
- Slack Channel (House)
   - Section A (Neighborhood)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)
- Laptop (House)
   - Section B(Neighborhood)
- Article Cover (House)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)
   - Section C (Neighborhood)
- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)
   - Footer (Neighborhood)
- Navigation (Block)
- Branding (House)
- Demo Link (House)

Note I have put the components that will be used multiple times in bold.

Alright, sweet!

Next, let’s open our project folder in Atom and take another look at the components folders we created:

Let’s add files into the components folders to reflect the component hierarchy that we just put together. For practice, see if you can do this yourself and create files in our project according to the proper hierarchy. When you are done, you can check with mine to see if you have done it correctly and adjust as needed.

Note: Keep the naming conventions as I have them when we put everything together. Meaning, we should keep spaces and capitalization of every work. Also, all files should end with .js (i.e. Call To Action.js).

Here is what we should have when we finish:

Cool beans. Go ahead and close any tabs that are open in Atom.

Understanding the Layout

Before we start creating the components, we need to understand how we would create this landing page using just HTML. That way, we can break the HTML into each of our individual components.

Rows and Columns

The main thing we need to understand is how can we achieve a proper layout for our user interface in HTML. When thinking about a proper layout, we need to be able to break down a user interface into rows and columns.

Let’s take a look at one of our sections:

How is this section laid out in terms of rows and columns?

Well, we only have 1 row of content:

However, there are 2 columns within this row:

Now, let’s compare this layout of rows and columns layout to our header:

First, let’s break this down in terms of rows:

We have 3 rows in total. Note that we keep the middle row as one row since those components work together as a block.

Next, let’s look at it in terms of columns:

In the image above, we have 2 columns in the first row, 1 column in the middle row, and 1 column in the bottom row.

Once we have the layout expressed in rows and columns, we can fill it in with the stuff we need.

Understanding Bootstrap’s Grid System

This begs the following question: “Can I define a layout in terms of rows and columns for out HTML?”

Yes. We can do this by making use of a grid system.

There’s a few options but let’s start with a popular option, Bootstrap.

Bootstrap is a framework for using predefined components (they do the CSS for us) in a UI and defining a grid system. I am not a fan of the former, but the latter is nice grid system for beginners.

Let’s jump into the HTML code using Bootstrap so we can better understand how this works.

Let’s look again at our section that we broke down into rows and columns:

Let’s apply the Bootstrap grid system and write the HTML code to define the layout (note that I will write this in HTML and not JSX).

First, we place an outermost div with a class for the name of our section (neighborhood):

<div class="section-a">
</div>

Then, we have to add a container within this div:

<section class="section-a">
<div class="container">
  </div>
</section>

Next, we create div elements with a class called row for each of our rows (just 1 in this example):

<section class="section-a">
<div class="container">
<div class="row">

</div>

</div>
</section>

To finish our layout, we add div elements for our columns. This will require a bit more explanation.

When it comes to columns within our layout, the width of the column is significant.

A column can have a width of at least 1/4 (25%) of the row and at most, it can take up the entire row (100%). In between 25% width and 100% width, we can have a column with a width of 33% (1/3 ) or a width of 50% (1/2). Therefore, our width options are:

  • 1/4
  • 1/3
  • 1/2
  • 1

Because of that, these are all the possibilities for how we can construct columns within a row:

With Bootstrap, the width of columns is expressed by whole numbers. Specifically, an entire row is expressed by the number 12.

If I want to express the widths of columns by 1/4, 1/3, 1/2, and 1, we do it by:

  • 3 (3/12 or 1/4)
  • 4 (4/12 or 1/3)
  • 6 (6/12 or 1/2)
  • 12 (12/12 or 1)

In Bootstrap, we specify a column and its width by the class like so:

<div class="col-lg-*insert whole number for width*"></div>

col is short for column.

lg has nothing to do with the width of the columns. Rather, it refers to how the grid system works across devices since it is a responsive grid system (responds to shrinking of the screen and display on mobile devices):

Let’s not worry about responsive design (for the sake of time) so I will use col-lg-___.

The last part of the syntax is to enter 3, 4, 6, or 12 to note the width of the column as was previously shown.

Our section has 2 columns that take up 1/2 of the row (col-lg-6):

Putting it all together, we can finish the code for our section like so:

<section class="section-a">
<div class="container">
<div class="row">
<div class="col-lg-6">
</div>
<div class="col-lg-6">
</div>

</div>
</div>
</section>

Just like that, we have been able to understand how to use Bootstrap’s grid system to define our layout for our sections.

react-grid-system: A Better Grid System Alternative

While I like using the Bootstrap grid system to explain the core concepts of working with a grid system, we are going to use an alternative for our JSX.

Reason being, Bootstrap has a lot of JavaScript that it modifies and we want to avoid conflicts with React. Therefore, we will use react-grid-system.

react-grid-system works very similarly to Bootstrap except our rows and columns are defined using React components and not CSS.

Let’s look at the react-grid-system implementation of the section we created with Bootstrap:

import { Container, Row, Col } from 'react-grid-system';
//stuff goes here...
//JSX returned in render function
<section class="section-a">
<Container>
<Row>
<Col lg={6}>
</Col>
<Col lg={6}>
</Col>
</Row>
</Container>

</section>

In the code above, we import the components we need from react-grid-system which will be installed via npm. Then, we just those use components in place of the Bootstrap classes. The same exact concepts with numbering the width of the columns applies.

Let’s go ahead and install this via npm:

npm install --save react-grid-system

Then, let’s test it out in our index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class App extends React.Component {
render() {
return (
<div className="section-a">
<Container>
<Row>
<Col lg={6}>
1/2 grid here!
</Col>
<Col lg={6}>
1/2 grid here!
</Col>
</Row>
</Container>
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);

Remember to save the file, open the root of this project in command line, and run:

npm start

Go to the local host address as noted in command line and we should see:

In our neighborhood components, we will have the JSX for the section and the container and rows. In our block components, we will have the columns and nested house components. In stand-alone house components, we will have the columns and whatever needs to go in between (no nested components).

Setting Up Our App

While we have index.js open, let’s remove all the JSX code and nest our village component which we know will be called LandingPage:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class App extends React.Component {
render() {
return (
<LandingPage/>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);

In the next chapter, we will add another village. For now, that is all we will have to do.

Setting Up Our Village

Landing Page

We have already created the file for our village called Landing Page.js and nested a component called LandingPage in our village.

Open that file and let’s go ahead and create this LandingPage component.

In this file, we need to import React, ReactDOM, and react-grid-system and have our JSX be all the nested neighborhoods. The neighborhoods will be Header, SectionA, SectionB, SectionC, and Footer.

Putting it together, we have:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class LandingPage extends React.Component {
render() {
return (
<div className="landing-page">
<Header/>
<SectionA/>
<SectionB/>
<SectionC/>
<Footer/>
</div>

)
}
}

Note there is no ReactDOM code because that should only happen at the top of the hierarchy which was taken care of in our index.js.

Setting Up Our Neighborhoods

The neighborhood components are going to render as section elements of our landing page. Here, we will be using the react-grid-system code that we looked at earlier. Specifically, our neighborhood components will use the Container component while the blocks or stand-alone houses will contain the rows and columns.

Header

Open Header.js and let’s create the shell of our Header component (no rows or columns):

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class Header extends React.Component {
render() {
return (
<section className="header">
<Container>

</Container>
</section>

)
}
}

Now, we need to fill in our Header with the rows and nested components. We want to nest only our blocks and the houses that aren’t under any blocks.

First off, we need to know how many rows are needed in our Header:

We will have 3 rows of content.

Next, let’s check to see what we need to nest:

- Header (Neighborhood)
- Navigation (Block)
- Branding (House)
- Demo Link (House)
- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)
- Slack Channel (House)

Knowing this, we can add the following:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class Header extends React.Component {
render() {
return (
<section className="header">
<Container>
<Row>
<Navigation/>
</Row>
<Row>
<CallToAction/>
</Row>
<Row>
<SlackChannel/>
</Row>

</Container>
</section>
)
}
}

Cool! We have added the 3 rows and the nested components which we will create later.

Section A

Open Section A.js so we can create the SectionA neighborhood component.

Again, we start by seeing how many rows of content there are:

We need 1 row of content.

We then just need to check what’s to be nested:

- Section A (Neighborhood)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)
- Laptop (House)

Based off of this, we can do:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class SectionA extends React.Component {
render() {
return (
<section className="section-a">
<Container>
<Row>
<SectionDescription/>
<Laptop/>
</Row>
</Container>
</section>
)
}
}

Section B

Let’s move on to Section B.js.

Section B is just like the previous section in that there is only 1 row of content.

In this file, we need the following components nested:

- Section B(Neighborhood)
- Article Cover (House)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)

Therefore, we can do:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class SectionB extends React.Component {
render() {
return (
<section className="section-b">
<Container>
<Row>
<ArticleCover/>
<SectionDescription/>
</Row>
</Container>
</section>
)
}
}

We should be familiar with the process for our neighborhoods at this point. For the final two components, I will just paste the needed components and code.

Section C

Section C nested components:

- Section C (Neighborhood)
- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)

Section C.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class SectionC extends React.Component {
render() {
return (
<section className="section-c">
<Container>
<Row>
<CallToAction/>
</Row>
</Container>
</section>
)
}
}

Footer

Footer nested components:

- Footer (Neighborhood)
- Navigation (Block)
- Branding (House)
- Demo Link (House)

Footer.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class Footer extends React.Component {
render() {
return (
<section className="footer">
<Container>
<Row>
<Navigation/>
</Row>
</Container>
</section>
)
}
}

Save everything and let’s move on to our blocks!

Setting Up Our Blocks

As we mentioned before, the block components will contain the react-grid-system code for the columns as well as the nested houses.

Let’s look at the houses we already nested in each neighborhood in the previous section and knock them out.

Header Blocks

Starting with our Header, we nested the following block components:

<Navigation/>
<CallToAction/>

The first thing to figure out is how these will be broken down into columns.

Let’s take a look at our header mockup:

Our Call to Action block is a bit more clear. It will only be 1 column and everything will be centered with CSS. If you recall, a full-width column is represented by the number 12.

Open Call To Action.js and let’s put in the following:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class CallToAction extends React.Component {
render() {
return (
<Col lg={12}>
      </Col>
)
}
}

Next, we just need to fill in our column with the nested houses:

- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)

Putting it all together, we have:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class CallToAction extends React.Component {
render() {
return (
<Col lg={12}>
<Title/>
<Subtitle/>
<Button/>
</Col>
)
}
}

Perfect.

Let’s move on to Navigation.js. This block is a bit more tricky to describe.

Because we have two components hugging the edges, it might be hard to visualize the columns. However, we can break it down into 2 columns like we have shown before and use CSS to hug the edges:

Let’s look at the components to that will be nested in these columns:

- Navigation (Block)
- Branding (House)
- Demo Link (House)

Therefore, we can add the following code:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class Navigation extends React.Component {
render() {
return (
<Col lg={6}>
<Branding/>
</Col>
<Col lg={6}>
<DemoLink/>
</Col>

)
}
}

Section A Blocks

Let’s see what blocks are in Section A:

<SectionDescription/>

Next, we look to see how our SectionDescription component can be broken down into rows and columns:

There will be 2 columns for our content.

Finally, let’s look at the nested blocks within SectionDescription before we add the code:

- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)

Putting it all together, we get the following for SectionDescription.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class SectionDescription extends React.Component {
render() {
return (
<Col lg={6}>
<Heading/>
<Divider/>
<Paragraph/>
</Col>

)
}
}

Section B Blocks

The SectionB component has the same block as SectionA which we have already created the file for.

Section C Blocks

The SectionC component has the same block, CallToAction, as the Header component. Nothing else needs to be done.

Footer Blocks

The Footer component has the same block, Navigation, as was used in the Header component. Once again, nothing else needs to be done.

Cool beans! Off to our houses!

Setting Up Our Houses

Almost done setting up all of our components, hang in there!

As we have mentioned before, there are house components that will be nested in block components and houses components that will be nested in neighborhoods (stand-alone house components).

Our house components will not have anything nested. They are the building blocks of our user interface. For these reasons, the JSX will be more familiar to what is typically done with straight HTML.

The stand-alone components will require a little bit more code since we still have to add the react-grid-system rows and columns.

Since we just finished up our block components, let’s do the house components that will go into our blocks.

Houses for Our Blocks

First, let’s look at all that we have to knock out:

- Navigation (Block)
- Branding (House)
- Demo Link (House)
- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)

Starting with Branding.js, we just have to render the image of our logo which is an SVG file. Download it here:

Even though it is an SVG, we can render in an img tag just like you would with a PNG or JPG image.

Before we write the code, however, let’s add a new folder in our project called images. This should go directly under react-landing-page like so:

Next, make sure to place the downloaded Branding.svg file under the images folder.

After that, we can move on to our code:

import React from 'react';
import ReactDOM from 'react-dom';
class Branding extends React.Component {
render() {
return (
<div>
<img className="branding" src="./images/Branding.svg" />
</div>
)
}
}

Remember that we always include an outermost div element in the JSX.

Next up, let’s do the DemoLink component to finish up the Navigation block.

In this component, we want to simply return a link. We have not discussed what this will link to so the href should be #.

Open up Demo Link.js and add the following:

import React from 'react';
import ReactDOM from 'react-dom';
class DemoLink extends React.Component {
render() {
return (
<div>
<a href="#">
<span className="demo-link">
Demo
</span>
</a>
</div>
)
}
}

The rest of the house components that will go into our block components are pretty easy to create. The process is to simply look at the mockup and translate it to JSX.

Try to give yourself a challenge and write the code without looking for the remaining house components:

- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)

There are some things you won’t be able to know.

One is what heading I will use for the title, subtitle, and heading. In that same order, let’s h1, h3, and h2.

You can also keep all the classes the same name as the component just with all lowercase.

Additionally, you can use this for the paragraph text:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent volutpat, elit pulvinar aliquam convallis, libero mauris rhoncus erat, non porttitor lectus justo et ex. In hac habitasse platea dictumst.

Finally, you can ignore writing the JSX for the Slack icon in the Button component.

Now give it a whirl!


Now that you have attempted this on your own, review the code for the remaining files:

Title.js

import React from 'react';
import ReactDOM from 'react-dom';
class Title extends React.Component {
render() {
return (
<div>
<h1 className="title">Developer Bot for Slack</h1>
</div>
)
}
}

Subtitle.js

import React from 'react';
import ReactDOM from 'react-dom';
class Subtitle extends React.Component {
render() {
return (
<div>
<h3 className="subtitle">One article to one random person in your Slack group. Once a day.</h3>
</div>
)
}
}

Button.js

import React from 'react';
import ReactDOM from 'react-dom';
class Button extends React.Component {
render() {
return (
<div>
<button className="button">Add to Slack</button>
</div>
)
}
}

Heading.js

import React from 'react';
import ReactDOM from 'react-dom';
class Heading extends React.Component {
render() {
return (
<div>
<h2 className="heading">
DevBot analyzes popular articles
</h2>
</div>
)
}
}

Paragraph.js

import React from 'react';
import ReactDOM from 'react-dom';
class Paragraph extends React.Component {
render() {
return (
<div>
<p className="paragraph">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent volutpat, elit pulvinar aliquam convallis, libero mauris rhoncus erat, non porttitor lectus justo et ex. In hac habitasse platea dictumst.
</p>
</div>
)
}
}

Divider.js

import React from 'react';
import ReactDOM from 'react-dom';
class Divider extends React.Component {
render() {
return (
<div>
<hr className="divider"/>
</div>
)
}
}

Once you are caught up, it’s time to move on to our stand-alone house components.

Stand-Alone Houses

Our stand-alone houses will be very similar to the previous house components we just completed. There is only one extra step. We have to include the react-grid-system code for defining our columns since there are no blocks for these houses were that step would occur.

Let’s look at what stand-alone houses we need:

- App
- Landing Page (Village)
- Header (Neighborhood)
- Navigation (Block)
- Branding (House)
- Demo Link (House)
- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)
- Slack Channel (House)
- Section A (Neighborhood)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)
- Laptop (House)
- Section B(Neighborhood)
- Article Cover (House)
- Section Description (Block)
- Heading (House)
- Divider (House)
- Paragraph (House)
- Section C (Neighborhood)
- Call To Action (Block)
- Title (House)
- Subtitle (House)
- Button (House)
- Footer (Neighborhood)
- Navigation (Block)
- Branding (House)
- Demo Link (House)

Let’s knock these out to finish off our component setup!

Starting with our SlackChannel component. This component will just be an SVG image.

As we can see below, it will only be one column:

The SVG image can be grabbed here and then moved under the images folder.

Therefore, we can do the following in our Slack Channel.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class SlackChannel extends React.Component {
render() {
return (
<Col lg={12}>
<img className="slack-channel" src="./images/Slack Channel.svg" />
</Col>
)
}
}

Our last two houses are very similar. Both of them will be an image in a section that is one column that takes up half of the row, therefore, the column can be expressed in the number 6.

First, grab the Laptop.svg file, move it to the images folder, and open Laptop.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class Laptop extends React.Component {
render() {
return (
<Col lg={6}>
<img className="laptop" src="./images/Laptop.svg" />
</Col>
)
}
}

Next, the ArticleCover component will just need a few tweaks from the previous code.

Make sure to grab the ArticleCover.svg file, move it under images, and open Article Cover.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class ArticleCover extends React.Component {
render() {
return (
<Col lg={6}>
<img className="article-cover" src="./images/Article Cover.svg" />
</Col>
)
}
}

Finally!!! We have completed the setup of all our components. However, nothing will work until we add the code for the module system.

Implementing the Module System

In the previous chapter, we discussed a new problem that is created by breaking down our component hierarchy into separate files.

For example, we just created our ArticleCover component in its own file called Article Cover.js. It is used in our SectionB component like so:

class SectionB extends React.Component {
render() {
return (
<section className="section-b">
<Container>
<Row>
<ArticleCover/>
</Row>
<Row>
<SectionDescription/>
</Row>
</Container>
</section>
)
}
}

How does this file know what <ArticleCover/> is if it was defined in another file?

Currently, it doesn’t. Therefore, we some code in Article Cover.js that will say: “Hey! I know we are making our ArticleCover component in this file, but I kinda want to use it somewhere else. I’m going to write some code so it can be imported in Section B.js where we will need to use it.”

Writing code that makes our components exportable and importable is done by a module system. With ES6, there is a module system built in that we can make use of.

Since we brought up our ArticleCover component, let’s test out this module system there.

Alright, you might be thinking: “Module system sounds pretty brutal concept! Please tell me this isn’t going to be like all the Webpack nonsense.”

Relax, it’s actually incredibly simple.

We only need to add this one line of code at the end of the Article Cover.js file:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
class ArticleCover extends React.Component {
render() {
return (
<Col lg={6}>
<img className="article-cover" src="./images/Article Cover.svg" />
</Col>
)
}
}
module.exports = ArticleCover;

That’s right. It’s that simple.

Now, let’s look at how we can do the import in Section B.js.

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
import ArticleCover from './components/villages/neighborhoods/blocks/houses/Article Cover.js';
class SectionB extends React.Component {
render() {
return (
<section className="section-b">
<Container>
<Row>
<ArticleCover/>
</Row>
<Row>
<SectionDescription/>
</Row>
</Container>
</section>
)
}
}

Simple as that! We just have to import using the following syntax:

import *whatever was assigned to Module.exports* from *insert path*

Note the path relative to the file you are editing or creating.

We’ve had a lot of coding to do in this section and I bet you are dying to see some results. Let’s test this out to make sure it is working correctly.

We will update index.js so it will import the ArticleCover component:

import React from 'react';
import ReactDOM from 'react-dom';
import { Container, Row, Col } from 'react-grid-system';
import ArticleCover from './components/villages/neighborhoods/blocks/houses/Article Cover.js';
class App extends React.Component {
render() {
return (
<ArticleCover/>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);

Now, go to command line and run:

npm start

Sweeet…it really works!!!!!

Go ahead and undo those changes in index.js.

The next step would be to add the exports and imports to all of our files.

However, you can simply review the final code that I will provide shortly.

Sprinkling Some Style

While I would love to take the time to unpack how I do the CSS to put this user interface together, that’s just way too much to fit into this chapter (plus this is about React).

Therefore, let’s just add a new file under the styles folder called landing-page.css and copy the following code:

@import url('https://fonts.googleapis.com/css?family=Lato:100,300,400,700,900');
body {
margin: 0;
padding: 0;
}
.header {
padding-top: 50px;
padding-bottom: 50px;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 1280 800' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd'%3E%3CclipPath id='a'%3E%3Cpath d='M1241.49 209H1280v94h-38.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23a)'%3E%3Cpath d='M1241.49 270l72 33 95-293-167 260z' fill='%237d90bd' fill-rule='nonzero' stroke='%237d90bd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='b'%3E%3Cpath d='M1197.49 495H1280v217h-82.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23b)'%3E%3Cpath d='M1293.49 470l-96 177 157 65-61-242z' fill='%235f85b6' fill-rule='nonzero' stroke='%235f85b6' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='c'%3E%3Cpath d='M1121.49 0H1280v270h-158.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23c)'%3E%3Cpath d='M1093.49-91l148 361 167-260-315-101z' fill='%238798c5' fill-rule='nonzero' stroke='%238798c5' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='d'%3E%3Cpath d='M1197.49 647H1280v87h-82.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23d)'%3E%3Cpath d='M1197.49 647l140 105 17-40-157-65z' fill='%23547eb3' fill-rule='nonzero' stroke='%23547eb3' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='e'%3E%3Cpath d='M1241.49 270H1280v200h-38.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23e)'%3E%3Cpath d='M1241.49 270l52 200 20-167-72-33z' fill='%23768dbd' fill-rule='nonzero' stroke='%23768dbd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='f'%3E%3Cpath d='M1197.49 616H1280v205h-82.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23f)'%3E%3Cpath d='M1197.49 647l99 174 41-69-140-105z' fill='%23507db3' fill-rule='nonzero' stroke='%23507db3' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='g'%3E%3Cpath d='M913.49 0h335v270h-335z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23g)'%3E%3Cpath d='M1093.49-91l-180 263 328 98-148-361z' fill='%23889fcd' fill-rule='nonzero' stroke='%23889fcd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='h'%3E%3Cpath d='M1045.49 270H1280v200h-234.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23h)'%3E%3Cpath d='M1241.49 270l-196 59 248 141-52-200z' fill='%237892c4' fill-rule='nonzero' stroke='%237892c4' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='i'%3E%3Cpath d='M906.494 0h138v172h-138z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23i)'%3E%3Cpath d='M906.494 73l7 99 180-263-187 164z' fill='%238ea7d3' fill-rule='nonzero' stroke='%238ea7d3' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='j'%3E%3Cpath d='M1071.49 470H1280v177h-208.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23j)'%3E%3Cpath d='M1071.49 634l126 13 96-177-222 164z' fill='%23648bbd' fill-rule='nonzero' stroke='%23648bbd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='k'%3E%3Cpath d='M1071.49 634H1280v166h-208.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23k)'%3E%3Cpath d='M1197.49 647l-126-13 225 187-99-174z' fill='%235785bb' fill-rule='nonzero' stroke='%235785bb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='l'%3E%3Cpath d='M1045.49 634h251v166h-251z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23l)'%3E%3Cpath d='M1053.49 610l-42 363 285-152-243-211z' fill='%234a82bb' fill-rule='nonzero' stroke='%234a82bb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='m'%3E%3Cpath d='M1045.49 329H1280v305h-234.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23m)'%3E%3Cpath d='M1045.49 329l26 305 222-164-248-141z' fill='%236f91c3' fill-rule='nonzero' stroke='%236f91c3' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M913.494 172l132 157 196-59-328-98z' fill='%23819ccb' fill-rule='nonzero' stroke='%23819ccb' stroke-width='1.51'/%3E%3CclipPath id='n'%3E%3Cpath d='M921.494 634h149.996v166H921.494z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23n)'%3E%3Cpath d='M921.494 800h134l16-166-150 229v-63z' fill='%234b87bf' fill-rule='nonzero' stroke='%234b87bf' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='o'%3E%3Cpath d='M660.494 0h433v68h-433z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23o)'%3E%3Cpath d='M518.494-46l271 114 304-159-562 35-13 10z' fill='%2396b2d9' fill-rule='nonzero' stroke='%2396b2d9' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M1045.49 329l-350 101 376 204-26-305z' fill='%23749bcb' fill-rule='nonzero' stroke='%23749bcb' stroke-width='1.51'/%3E%3Cpath d='M695.494 430l7 211c120.646-1.857 173.135 1.994 369-7l-376-204z' fill='%236d9ecc' fill-rule='nonzero' stroke='%236d9ecc' stroke-width='1.52'/%3E%3CclipPath id='p'%3E%3Cpath d='M789.494 0h248v73h-248z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23p)'%3E%3Cpath d='M789.494 68l117 5 187-164-304 159z' fill='%2390aad5' fill-rule='nonzero' stroke='%2390aad5' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M913.494 172l-218 258 350-101-132-157z' fill='%2381a3d1' fill-rule='nonzero' stroke='%2381a3d1' stroke-width='1.51'/%3E%3Cpath d='M695.494 131v299l218-258-218-41z' fill='%2388acd6' fill-rule='nonzero' stroke='%2388acd6' stroke-width='1.51'/%3E%3CclipPath id='q'%3E%3Cpath d='M702.494 638h182v162h-182z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23q)'%3E%3Cpath d='M702.494 638l133 265 86-40-219-225z' fill='%235292c7' fill-rule='nonzero' stroke='%235292c7' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M906.494 73l-117-5 124 104-7-99z' fill='%238daad5' fill-rule='nonzero' stroke='%238daad5' stroke-width='1.51'/%3E%3Cpath d='M789.494 68l-94 63 218 41-124-104z' fill='%238eaed7' fill-rule='nonzero' stroke='%238eaed7' stroke-width='1.51'/%3E%3CclipPath id='r'%3E%3Cpath d='M474.494 638h337.5v162h-337.5z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23r)'%3E%3Cpath d='M702.494 638l-228 145 361 120-133-265z' fill='%235a9acb' fill-rule='nonzero' stroke='%235a9acb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='s'%3E%3Cpath d='M474.494 783h197v17h-197z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23s)'%3E%3Cpath d='M474.494 783l140 242 221-122-361-120z' fill='%234d95c8' fill-rule='nonzero' stroke='%234d95c8' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M695.494 131l-174 62 174 237V131z' fill='%238cb2d9' fill-rule='nonzero' stroke='%238cb2d9' stroke-width='1.51'/%3E%3CclipPath id='t'%3E%3Cpath d='M566.494 0h223v131h-223z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23t)'%3E%3Cpath d='M500.494-91l195 222 94-63-289-159z' fill='%2396b7dc' fill-rule='nonzero' stroke='%2396b7dc' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M695.494 430l-126 32 133 176-7-208z' fill='%2379a8d3' fill-rule='nonzero' stroke='%2379a8d3' stroke-width='1.51'/%3E%3CclipPath id='u'%3E%3Cpath d='M513.494 0h182v193h-182z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23u)'%3E%3Cpath d='M531.494-56l-10 249 174-62-164-187z' fill='%2397badd' fill-rule='nonzero' stroke='%2397badd' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M521.494 193l48 269 126-32-174-237z' fill='%2387b0d8' fill-rule='nonzero' stroke='%2387b0d8' stroke-width='1.51'/%3E%3Cpath d='M569.494 462l-105 74 238 102-133-176z' fill='%2378abd3' fill-rule='nonzero' stroke='%2378abd3' stroke-width='1.51'/%3E%3Cpath d='M464.494 536l10 247 228-145-238-102z' fill='%236da8d1' fill-rule='nonzero' stroke='%236da8d1' stroke-width='1.51'/%3E%3CclipPath id='v'%3E%3Cpath d='M0 0h531.494v75H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23v)'%3E%3Cpath d='M-136.506-41l310 116 358-131-668 15z' fill='%23adcfe8' fill-rule='nonzero' stroke='%23adcfe8' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M464.494 536l-6 241 16 6-10-247z' fill='%236ba9d2' fill-rule='nonzero' stroke='%236ba9d2' stroke-width='1.51'/%3E%3Cpath d='M521.494 193l-90 224 138 45-48-269z' fill='%238ab5da' fill-rule='nonzero' stroke='%238ab5da' stroke-width='1.51'/%3E%3CclipPath id='w'%3E%3Cpath d='M381.494 783h207v17h-207z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23w)'%3E%3Cpath d='M474.494 783l-93 301 233-59-140-242z' fill='%234d99ca' fill-rule='nonzero' stroke='%234d99ca' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='x'%3E%3Cpath d='M173.494 0h269v84h-269z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23x)'%3E%3Cpath d='M173.494 75l100 9 258-140-358 131z' fill='%23a5c8e4' fill-rule='nonzero' stroke='%23a5c8e4' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M350.494 702l108 75 6-241-114 166z' fill='%2370acd4' fill-rule='nonzero' stroke='%2370acd4' stroke-width='1.51'/%3E%3Cpath d='M273.494 84l82 131 166-22-248-109z' fill='%239bc1e1' fill-rule='nonzero' stroke='%239bc1e1' stroke-width='1.51'/%3E%3Cpath d='M355.494 215l76 202 90-224-166 22z' fill='%2392bbdd' fill-rule='nonzero' stroke='%2392bbdd' stroke-width='1.51'/%3E%3CclipPath id='y'%3E%3Cpath d='M273.494 0h258v193h-258z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23y)'%3E%3Cpath d='M273.494 84l248 109 10-249-258 140z' fill='%239dc1e1' fill-rule='nonzero' stroke='%239dc1e1' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M431.494 417l33 119 105-74-138-45z' fill='%2381b2d8' fill-rule='nonzero' stroke='%2381b2d8' stroke-width='1.51'/%3E%3CclipPath id='z'%3E%3Cpath d='M395.494 777h79v23h-79z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23z)'%3E%3Cpath d='M458.494 777l-77 307 93-301-16-6z' fill='%23589fcd' fill-rule='nonzero' stroke='%23589fcd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='A'%3E%3Cpath d='M370.494 777h88v23h-88z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23A)'%3E%3Cpath d='M226.494 986l155 98 77-307-232 209z' fill='%23579fcd' fill-rule='nonzero' stroke='%23579fcd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='B'%3E%3Cpath d='M299.494 702h159v98h-159z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23B)'%3E%3Cpath d='M350.494 702l-124 284 232-209-108-75z' fill='%2362a7d2' fill-rule='nonzero' stroke='%2362a7d2' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M431.494 417l-196 224 229-105-33-119z' fill='%2381b5d8' fill-rule='nonzero' stroke='%2381b5d8' stroke-width='1.51'/%3E%3Cpath d='M235.494 641l115 61 114-166-229 105z' fill='%2379b2d6' fill-rule='nonzero' stroke='%2379b2d6' stroke-width='1.51'/%3E%3CclipPath id='C'%3E%3Cpath d='M171.494 702h179v98h-179z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23C)'%3E%3Cpath d='M181.494 752l45 234 124-284-169 50z' fill='%2369abd4' fill-rule='nonzero' stroke='%2369abd4' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M355.494 215l-230 186 306 16-76-202z' fill='%2395bfe0' fill-rule='nonzero' stroke='%2395bfe0' stroke-width='1.51'/%3E%3Cpath d='M125.494 401l110 240 196-224-306-16z' fill='%238bbbdc' fill-rule='nonzero' stroke='%238bbbdc' stroke-width='1.51'/%3E%3Cpath d='M105.494 290l20 111 230-186-250 75z' fill='%239cc5e3' fill-rule='nonzero' stroke='%239cc5e3' stroke-width='1.51'/%3E%3Cpath d='M273.494 84l-168 206 250-75-82-131z' fill='%23a0c6e3' fill-rule='nonzero' stroke='%23a0c6e3' stroke-width='1.51'/%3E%3Cpath d='M235.494 641l-54 111 169-50-115-61z' fill='%2376b2d7' fill-rule='nonzero' stroke='%2376b2d7' stroke-width='1.51'/%3E%3CclipPath id='D'%3E%3Cpath d='M126.494 752h100v48h-100z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23D)'%3E%3Cpath d='M181.494 752l-142 227 187 7-45-234z' fill='%2366aad4' fill-rule='nonzero' stroke='%2366aad4' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M173.494 75l-68 215 168-206-100-9z' fill='%23a5cae5' fill-rule='nonzero' stroke='%23a5cae5' stroke-width='1.51'/%3E%3CclipPath id='E'%3E%3Cpath d='M0 591h235.494v161H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23E)'%3E%3Cpath d='M-96.506 575l278 177 54-111-332-66z' fill='%2383badb' fill-rule='nonzero' stroke='%2383badb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='F'%3E%3Cpath d='M0 401h273.494v260H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23F)'%3E%3Cpath d='M125.494 401l-222 174 332 66-110-240z' fill='%2390c1df' fill-rule='nonzero' stroke='%2390c1df' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='G'%3E%3Cpath d='M0 401h125.494v97H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23G)'%3E%3Cpath d='M-60.506 417l-36 158 222-174-186 16z' fill='%239ec7e2' fill-rule='nonzero' stroke='%239ec7e2' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='H'%3E%3Cpath d='M81.494 752h100v48h-100z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23H)'%3E%3Cpath d='M-41.506 920l81 59 142-227-223 168z' fill='%236fafd6' fill-rule='nonzero' stroke='%236fafd6' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='I'%3E%3Cpath d='M0 75h173.494v232H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23I)'%3E%3Cpath d='M-54.506 307l160-17 68-215-228 232z' fill='%23a8cce6' fill-rule='nonzero' stroke='%23a8cce6' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='J'%3E%3Cpath d='M0 575h181.494v225H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23J)'%3E%3Cpath d='M-96.506 575l55 345 223-168-278-177z' fill='%2380b9da' fill-rule='nonzero' stroke='%2380b9da' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='K'%3E%3Cpath d='M0 0h173.494v307H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23K)'%3E%3Cpath d='M-136.506-41l82 348 228-232-310-116z' fill='%23b3d3e9' fill-rule='nonzero' stroke='%23b3d3e9' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='L'%3E%3Cpath d='M0 288h125.494v113H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23L)'%3E%3Cpath d='M105.494 290l-160 17 180 94-20-111z' fill='%23a3c9e5' fill-rule='nonzero' stroke='%23a3c9e5' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='M'%3E%3Cpath d='M0 333h125.494v84H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23M)'%3E%3Cpath d='M-54.506 307l-6 110 186-16-180-94z' fill='%23a4cae5' fill-rule='nonzero' stroke='%23a4cae5' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='N'%3E%3Cpath d='M702.494 634h363v166h-363z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23N)'%3E%3Cpath d='M702.494 638l219 255 232.496-317-130.562 58.52L702.494 638z' fill='%235b92c6' fill-rule='nonzero' stroke='%235b92c6' stroke-width='1.51'/%3E%3C/g%3E%3Cpath fill='url(%23O)' d='M0 0h1280v800H0z'/%3E%3Cdefs%3E%3ClinearGradient id='O' x2='1' gradientUnits='userSpaceOnUse' gradientTransform='rotate(148.597 640 179.91) scale(1462.167)'%3E%3Cstop offset='0' stop-color='%235490cd' stop-opacity='.329'/%3E%3Cstop offset='.49' stop-color='%235662c2' stop-opacity='.729'/%3E%3Cstop offset='1' stop-color='%235653bf' stop-opacity='.855'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E");
background-size: cover;
}
.branding {
position: absolute;
left: 0;
width: 20%;
cursor: pointer;
z-index: 2;
}
a {
text-decoration: none;
font-family: "Lato";
font-weight: 300;
text-align: right;
cursor: pointer;
}
.demo-link {
cursor: pointer;
z-index: 2;
position: absolute;
right: 0px;
color: white;
}
.slack-channel {
position: relative;
width: 40%;
display: block;
margin: auto;
bottom: -50px;
}
.title, .subtitle{
text-align: center;
font-family: "Lato";
color: white;
}
.title {
margin-top: 50px;
font-weight: 700;
font-size: 40px;
}
.subtitle {
margin-top: -20px;
font-weight: 100;
font-size: 20px;
letter-spacing: 0.5px;
}
.button {
position: relative;
margin: auto;
display: block;
margin-top: 30px;
padding: 10px 30px;
background: #5EDBB1;
border-radius: 40px;
color: white;
font-weight: 400;
font-size: 20px;
font-family: "Lato";
border: none;
}
.section-a, .section-b {
padding-top: 40px;
padding-bottom: 40px;
background: #FAFAFC;
}
.heading, .paragraph {
color: #2F3133;
font-family: "Lato";
}
.heading {
font-size: 36px;
font-weight: 700px;
}
hr {
max-width: 60px;
margin: 0px;
margin-top: -20px;
background: #8D90D4;
}
.paragraph {
font-size: 16px;
font-weight: 100px;
line-height: 2;
letter-spacing: 2;
}
.section-c {
padding-top: 20px;
padding-bottom: 60px;
background: #FAFAFC;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 1280 800' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' clip-rule='evenodd'%3E%3CclipPath id='a'%3E%3Cpath d='M1241.49 209H1280v94h-38.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23a)'%3E%3Cpath d='M1241.49 270l72 33 95-293-167 260z' fill='%237d90bd' fill-rule='nonzero' stroke='%237d90bd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='b'%3E%3Cpath d='M1197.49 495H1280v217h-82.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23b)'%3E%3Cpath d='M1293.49 470l-96 177 157 65-61-242z' fill='%235f85b6' fill-rule='nonzero' stroke='%235f85b6' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='c'%3E%3Cpath d='M1121.49 0H1280v270h-158.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23c)'%3E%3Cpath d='M1093.49-91l148 361 167-260-315-101z' fill='%238798c5' fill-rule='nonzero' stroke='%238798c5' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='d'%3E%3Cpath d='M1197.49 647H1280v87h-82.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23d)'%3E%3Cpath d='M1197.49 647l140 105 17-40-157-65z' fill='%23547eb3' fill-rule='nonzero' stroke='%23547eb3' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='e'%3E%3Cpath d='M1241.49 270H1280v200h-38.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23e)'%3E%3Cpath d='M1241.49 270l52 200 20-167-72-33z' fill='%23768dbd' fill-rule='nonzero' stroke='%23768dbd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='f'%3E%3Cpath d='M1197.49 616H1280v205h-82.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23f)'%3E%3Cpath d='M1197.49 647l99 174 41-69-140-105z' fill='%23507db3' fill-rule='nonzero' stroke='%23507db3' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='g'%3E%3Cpath d='M913.49 0h335v270h-335z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23g)'%3E%3Cpath d='M1093.49-91l-180 263 328 98-148-361z' fill='%23889fcd' fill-rule='nonzero' stroke='%23889fcd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='h'%3E%3Cpath d='M1045.49 270H1280v200h-234.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23h)'%3E%3Cpath d='M1241.49 270l-196 59 248 141-52-200z' fill='%237892c4' fill-rule='nonzero' stroke='%237892c4' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='i'%3E%3Cpath d='M906.494 0h138v172h-138z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23i)'%3E%3Cpath d='M906.494 73l7 99 180-263-187 164z' fill='%238ea7d3' fill-rule='nonzero' stroke='%238ea7d3' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='j'%3E%3Cpath d='M1071.49 470H1280v177h-208.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23j)'%3E%3Cpath d='M1071.49 634l126 13 96-177-222 164z' fill='%23648bbd' fill-rule='nonzero' stroke='%23648bbd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='k'%3E%3Cpath d='M1071.49 634H1280v166h-208.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23k)'%3E%3Cpath d='M1197.49 647l-126-13 225 187-99-174z' fill='%235785bb' fill-rule='nonzero' stroke='%235785bb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='l'%3E%3Cpath d='M1045.49 634h251v166h-251z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23l)'%3E%3Cpath d='M1053.49 610l-42 363 285-152-243-211z' fill='%234a82bb' fill-rule='nonzero' stroke='%234a82bb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='m'%3E%3Cpath d='M1045.49 329H1280v305h-234.51z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23m)'%3E%3Cpath d='M1045.49 329l26 305 222-164-248-141z' fill='%236f91c3' fill-rule='nonzero' stroke='%236f91c3' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M913.494 172l132 157 196-59-328-98z' fill='%23819ccb' fill-rule='nonzero' stroke='%23819ccb' stroke-width='1.51'/%3E%3CclipPath id='n'%3E%3Cpath d='M921.494 634h149.996v166H921.494z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23n)'%3E%3Cpath d='M921.494 800h134l16-166-150 229v-63z' fill='%234b87bf' fill-rule='nonzero' stroke='%234b87bf' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='o'%3E%3Cpath d='M660.494 0h433v68h-433z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23o)'%3E%3Cpath d='M518.494-46l271 114 304-159-562 35-13 10z' fill='%2396b2d9' fill-rule='nonzero' stroke='%2396b2d9' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M1045.49 329l-350 101 376 204-26-305z' fill='%23749bcb' fill-rule='nonzero' stroke='%23749bcb' stroke-width='1.51'/%3E%3Cpath d='M695.494 430l7 211c120.646-1.857 173.135 1.994 369-7l-376-204z' fill='%236d9ecc' fill-rule='nonzero' stroke='%236d9ecc' stroke-width='1.52'/%3E%3CclipPath id='p'%3E%3Cpath d='M789.494 0h248v73h-248z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23p)'%3E%3Cpath d='M789.494 68l117 5 187-164-304 159z' fill='%2390aad5' fill-rule='nonzero' stroke='%2390aad5' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M913.494 172l-218 258 350-101-132-157z' fill='%2381a3d1' fill-rule='nonzero' stroke='%2381a3d1' stroke-width='1.51'/%3E%3Cpath d='M695.494 131v299l218-258-218-41z' fill='%2388acd6' fill-rule='nonzero' stroke='%2388acd6' stroke-width='1.51'/%3E%3CclipPath id='q'%3E%3Cpath d='M702.494 638h182v162h-182z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23q)'%3E%3Cpath d='M702.494 638l133 265 86-40-219-225z' fill='%235292c7' fill-rule='nonzero' stroke='%235292c7' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M906.494 73l-117-5 124 104-7-99z' fill='%238daad5' fill-rule='nonzero' stroke='%238daad5' stroke-width='1.51'/%3E%3Cpath d='M789.494 68l-94 63 218 41-124-104z' fill='%238eaed7' fill-rule='nonzero' stroke='%238eaed7' stroke-width='1.51'/%3E%3CclipPath id='r'%3E%3Cpath d='M474.494 638h337.5v162h-337.5z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23r)'%3E%3Cpath d='M702.494 638l-228 145 361 120-133-265z' fill='%235a9acb' fill-rule='nonzero' stroke='%235a9acb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='s'%3E%3Cpath d='M474.494 783h197v17h-197z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23s)'%3E%3Cpath d='M474.494 783l140 242 221-122-361-120z' fill='%234d95c8' fill-rule='nonzero' stroke='%234d95c8' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M695.494 131l-174 62 174 237V131z' fill='%238cb2d9' fill-rule='nonzero' stroke='%238cb2d9' stroke-width='1.51'/%3E%3CclipPath id='t'%3E%3Cpath d='M566.494 0h223v131h-223z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23t)'%3E%3Cpath d='M500.494-91l195 222 94-63-289-159z' fill='%2396b7dc' fill-rule='nonzero' stroke='%2396b7dc' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M695.494 430l-126 32 133 176-7-208z' fill='%2379a8d3' fill-rule='nonzero' stroke='%2379a8d3' stroke-width='1.51'/%3E%3CclipPath id='u'%3E%3Cpath d='M513.494 0h182v193h-182z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23u)'%3E%3Cpath d='M531.494-56l-10 249 174-62-164-187z' fill='%2397badd' fill-rule='nonzero' stroke='%2397badd' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M521.494 193l48 269 126-32-174-237z' fill='%2387b0d8' fill-rule='nonzero' stroke='%2387b0d8' stroke-width='1.51'/%3E%3Cpath d='M569.494 462l-105 74 238 102-133-176z' fill='%2378abd3' fill-rule='nonzero' stroke='%2378abd3' stroke-width='1.51'/%3E%3Cpath d='M464.494 536l10 247 228-145-238-102z' fill='%236da8d1' fill-rule='nonzero' stroke='%236da8d1' stroke-width='1.51'/%3E%3CclipPath id='v'%3E%3Cpath d='M0 0h531.494v75H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23v)'%3E%3Cpath d='M-136.506-41l310 116 358-131-668 15z' fill='%23adcfe8' fill-rule='nonzero' stroke='%23adcfe8' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M464.494 536l-6 241 16 6-10-247z' fill='%236ba9d2' fill-rule='nonzero' stroke='%236ba9d2' stroke-width='1.51'/%3E%3Cpath d='M521.494 193l-90 224 138 45-48-269z' fill='%238ab5da' fill-rule='nonzero' stroke='%238ab5da' stroke-width='1.51'/%3E%3CclipPath id='w'%3E%3Cpath d='M381.494 783h207v17h-207z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23w)'%3E%3Cpath d='M474.494 783l-93 301 233-59-140-242z' fill='%234d99ca' fill-rule='nonzero' stroke='%234d99ca' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='x'%3E%3Cpath d='M173.494 0h269v84h-269z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23x)'%3E%3Cpath d='M173.494 75l100 9 258-140-358 131z' fill='%23a5c8e4' fill-rule='nonzero' stroke='%23a5c8e4' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M350.494 702l108 75 6-241-114 166z' fill='%2370acd4' fill-rule='nonzero' stroke='%2370acd4' stroke-width='1.51'/%3E%3Cpath d='M273.494 84l82 131 166-22-248-109z' fill='%239bc1e1' fill-rule='nonzero' stroke='%239bc1e1' stroke-width='1.51'/%3E%3Cpath d='M355.494 215l76 202 90-224-166 22z' fill='%2392bbdd' fill-rule='nonzero' stroke='%2392bbdd' stroke-width='1.51'/%3E%3CclipPath id='y'%3E%3Cpath d='M273.494 0h258v193h-258z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23y)'%3E%3Cpath d='M273.494 84l248 109 10-249-258 140z' fill='%239dc1e1' fill-rule='nonzero' stroke='%239dc1e1' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M431.494 417l33 119 105-74-138-45z' fill='%2381b2d8' fill-rule='nonzero' stroke='%2381b2d8' stroke-width='1.51'/%3E%3CclipPath id='z'%3E%3Cpath d='M395.494 777h79v23h-79z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23z)'%3E%3Cpath d='M458.494 777l-77 307 93-301-16-6z' fill='%23589fcd' fill-rule='nonzero' stroke='%23589fcd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='A'%3E%3Cpath d='M370.494 777h88v23h-88z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23A)'%3E%3Cpath d='M226.494 986l155 98 77-307-232 209z' fill='%23579fcd' fill-rule='nonzero' stroke='%23579fcd' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='B'%3E%3Cpath d='M299.494 702h159v98h-159z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23B)'%3E%3Cpath d='M350.494 702l-124 284 232-209-108-75z' fill='%2362a7d2' fill-rule='nonzero' stroke='%2362a7d2' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M431.494 417l-196 224 229-105-33-119z' fill='%2381b5d8' fill-rule='nonzero' stroke='%2381b5d8' stroke-width='1.51'/%3E%3Cpath d='M235.494 641l115 61 114-166-229 105z' fill='%2379b2d6' fill-rule='nonzero' stroke='%2379b2d6' stroke-width='1.51'/%3E%3CclipPath id='C'%3E%3Cpath d='M171.494 702h179v98h-179z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23C)'%3E%3Cpath d='M181.494 752l45 234 124-284-169 50z' fill='%2369abd4' fill-rule='nonzero' stroke='%2369abd4' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M355.494 215l-230 186 306 16-76-202z' fill='%2395bfe0' fill-rule='nonzero' stroke='%2395bfe0' stroke-width='1.51'/%3E%3Cpath d='M125.494 401l110 240 196-224-306-16z' fill='%238bbbdc' fill-rule='nonzero' stroke='%238bbbdc' stroke-width='1.51'/%3E%3Cpath d='M105.494 290l20 111 230-186-250 75z' fill='%239cc5e3' fill-rule='nonzero' stroke='%239cc5e3' stroke-width='1.51'/%3E%3Cpath d='M273.494 84l-168 206 250-75-82-131z' fill='%23a0c6e3' fill-rule='nonzero' stroke='%23a0c6e3' stroke-width='1.51'/%3E%3Cpath d='M235.494 641l-54 111 169-50-115-61z' fill='%2376b2d7' fill-rule='nonzero' stroke='%2376b2d7' stroke-width='1.51'/%3E%3CclipPath id='D'%3E%3Cpath d='M126.494 752h100v48h-100z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23D)'%3E%3Cpath d='M181.494 752l-142 227 187 7-45-234z' fill='%2366aad4' fill-rule='nonzero' stroke='%2366aad4' stroke-width='1.51'/%3E%3C/g%3E%3Cpath d='M173.494 75l-68 215 168-206-100-9z' fill='%23a5cae5' fill-rule='nonzero' stroke='%23a5cae5' stroke-width='1.51'/%3E%3CclipPath id='E'%3E%3Cpath d='M0 591h235.494v161H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23E)'%3E%3Cpath d='M-96.506 575l278 177 54-111-332-66z' fill='%2383badb' fill-rule='nonzero' stroke='%2383badb' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='F'%3E%3Cpath d='M0 401h273.494v260H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23F)'%3E%3Cpath d='M125.494 401l-222 174 332 66-110-240z' fill='%2390c1df' fill-rule='nonzero' stroke='%2390c1df' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='G'%3E%3Cpath d='M0 401h125.494v97H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23G)'%3E%3Cpath d='M-60.506 417l-36 158 222-174-186 16z' fill='%239ec7e2' fill-rule='nonzero' stroke='%239ec7e2' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='H'%3E%3Cpath d='M81.494 752h100v48h-100z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23H)'%3E%3Cpath d='M-41.506 920l81 59 142-227-223 168z' fill='%236fafd6' fill-rule='nonzero' stroke='%236fafd6' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='I'%3E%3Cpath d='M0 75h173.494v232H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23I)'%3E%3Cpath d='M-54.506 307l160-17 68-215-228 232z' fill='%23a8cce6' fill-rule='nonzero' stroke='%23a8cce6' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='J'%3E%3Cpath d='M0 575h181.494v225H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23J)'%3E%3Cpath d='M-96.506 575l55 345 223-168-278-177z' fill='%2380b9da' fill-rule='nonzero' stroke='%2380b9da' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='K'%3E%3Cpath d='M0 0h173.494v307H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23K)'%3E%3Cpath d='M-136.506-41l82 348 228-232-310-116z' fill='%23b3d3e9' fill-rule='nonzero' stroke='%23b3d3e9' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='L'%3E%3Cpath d='M0 288h125.494v113H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23L)'%3E%3Cpath d='M105.494 290l-160 17 180 94-20-111z' fill='%23a3c9e5' fill-rule='nonzero' stroke='%23a3c9e5' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='M'%3E%3Cpath d='M0 333h125.494v84H0z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23M)'%3E%3Cpath d='M-54.506 307l-6 110 186-16-180-94z' fill='%23a4cae5' fill-rule='nonzero' stroke='%23a4cae5' stroke-width='1.51'/%3E%3C/g%3E%3CclipPath id='N'%3E%3Cpath d='M702.494 634h363v166h-363z'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23N)'%3E%3Cpath d='M702.494 638l219 255 232.496-317-130.562 58.52L702.494 638z' fill='%235b92c6' fill-rule='nonzero' stroke='%235b92c6' stroke-width='1.51'/%3E%3C/g%3E%3Cpath fill='url(%23O)' d='M0 0h1280v800H0z'/%3E%3Cdefs%3E%3ClinearGradient id='O' x2='1' gradientUnits='userSpaceOnUse' gradientTransform='rotate(148.597 640 179.91) scale(1462.167)'%3E%3Cstop offset='0' stop-color='%235490cd' stop-opacity='.329'/%3E%3Cstop offset='.49' stop-color='%235662c2' stop-opacity='.729'/%3E%3Cstop offset='1' stop-color='%235653bf' stop-opacity='.855'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E");
background-size: cover;
}
.footer {
padding-top: 15px;
padding-bottom: 35px;
background: #666666;
}
.laptop, .article-cover {
position: relative;
margin: auto;
display: block;
width: 70%;
}

Lastly, we just add the link in our index.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React Landing Page</title>
<link rel="stylesheet" href="styles/landing-page.css">
</head>
<body>
<div id="app">
</div>
</body>
</html>

Feel free to explore the CSS and try to figure out how I went about all the styling.


Woohoo! We have successfully made our first user interface!

Final Code

Available here via Github

Note: I recommend trying to get all the import and exports to work after seeing a few examples of how I did it. Then, double check the final code.

When you have everything together, make sure to run:

npm start

Then, go to the local host to see the landing page.

Concluding Thoughts

I know that it has taken us seven chapters to finally get to make a user interface. However, I have no regrets about taking that much time to explain things. Too often, I have seen tutorials that start off setting the bar way too high. This leads to a lot of not so obvious terminologies being glanced over meanwhile fatigue increases for the learner. After all, if React teaches us the importance of breaking things down into smaller pieces, we should have the same approach to learning and teach it.

Anyways, give yourself a round of applause. Even though we need to make improvements and make things more dynamic, we have gained a lot of practical knowledge already.

In the next chapter, we will make some improvement to our current user interface and then move on to make a chat bot demo. Along the way, we will really use all that React has to offer and step out into the React ecosystem.

Chapter 8

Chapter 8 is now available here.

Get the Official Ebook

If you want to support me, you can go here to get an official copy of this ebook via PDF, MOBI, and EPUB.


Please provide kind correction and feedback. Smash the heart and share away.

Cheers,
Mike Mangialardi
Founder of Coding Artist