This page is a work in progress.You can help improve it. →

Hello, React

React

A JavaScript library for building user interfaces

React is the primary front end library/framework we will focus on for this course.

It was developed by Facebook around 2011/2012 and was released as an open source project in 2013.

From React's Homepage:

React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.

Build encapsulated components that manage their state, then compose them to make complex UIs.

We don’t make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code.

These are strong claims. Let's dive in and begin to see how React delivers on these promises.

Components

One of the main ideas of React is the concept of composing your web application from components. A component in React is a combination of state and behavior that serve to render elements to the DOM.

When learning HTML and CSS we decomposed our user interface into blocks and groups of elements to organize and then style the content of the page. The same is true of React Components. We can now also look at our pages as collections of React Components. Each of these components can be reused which will help us reduce code.

Class versus Function components

These are the two current ways to create React Components. class components were introduced first and you will see most documentation relate to this style. However, the React team, and the community as a whole, are migrating to function based components. In this course we will teach you the function component style. If you continue with React in your career and work on projects that use class components you won't have much trouble picking up that style.

What does a Component look like

The rules of a React component are:

  • It must be named following the PascalCase style.
  • It must be a function (function style or arrow-style) that returns JSX
  • The JSX returned must consist of exactly one main element, with other elements contained within. We'll see this more later.

Example:

function HelloWorld() {
return <p>Hello, World!</p>
}

What is JSX?

JSX is an extension of JavaScript that allows us to use an HTML-like syntax in our JavaScript code that will be turned into DOM at run-time. By using JSX we can dynamically generate content and use a UI as state style.

Simplest React Component

function HelloWorld() {
return <p>Hello, World!</p>
}

When this component is presented on the page it will render <p>Hello, World</p>. This done by a process known as transpiling or converting JSX into real JavaScript code. When our code is sent to the browser it is first manipulated by the JSX transpiling system. return <p>Hello, World!</p> is turned into:

function HelloWorld() {
return React.createElement('p', null, 'Hello, World')
}

We could code using the React.createElement style, but you would quickly realize that it is very tedious and "hides" the structure of the component we are trying to create.

If you'd like to experiment with any of the other examples in the handbook, you can visit: Babel REPL to see how JSX is transformed into plain JavaScript.

How do we use React Components?

React Components can represent the entire web page, or be mixed in with static content of the page.

In the code we write in our projects we will use React to generate all of the content on the page via components. React is very powerful for this but it is good to know that you can also add a small component to an existing non-React project just as easily.

The template SDG uses will generate an index.html file that looks like the following (only the <body> is shown and only the relevant parts)

<body>
<div id="root"></div>
</body>

If we rendered this without JavaScript it would be an empty page. It is thus up to JavaScript to connect our React code to our HTML.

In our template we include an main.tsx -- this script loads React and a component we provide named App

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)

React connects an existing DOM element to a component with the ReactDOM method. Here we state that the element with the id of root will be replaced with the component App that we import from the App.tsx file.

Typically we will not have to adjust the index.html or the main.tsx files. We will start writing our code in our App.tsx file.

JSX Files

You may have noticed that we define our React Components in files that end in .tsx instead of .ts. The .tsx extension allows our editors and our code management tools to know we are using the JSX extensions. Browsers do not understand JSX by default so a transpile step takes place automatically. This step turns our JSX into plain JavaScript that a browser can understand.

Build a simple React application

Let's generate a new project that will set up a new React project.

degit $GITHUB_USER/react-project-template ReactArticles

Initial HTML

This is some sample HTML we will work to create and learn how React Components can help simplify our code.

<div class="all-main-content">
<main>
<article class="intro-article">
<h2 className="article-title">SDG Announces Hackathon!</h2>
<p>
SDG announces the 2020 Summer Hackathon. Join us for an exciting weekend
</p>
<a class="read-more" href="#here">
read more about SDG Announces Hackathon!
</a>
</article>
<article class="intro-article">
<h2 className="article-title">
Student Graduation is Right Around the Corner
</h2>
<p>Our next cohort of students will be graduating in just over a week.</p>
<a class="read-more" href="#here">
read more about Student Graduation is Right Around the Corner
</a>
</article>
</main>
</div>

Start with hard coded content

Much like how we started with HTML, we want to get the content onto the page. Let's open up our main component, the App component, and put this static content on the page.

import React from 'react'
function App() {
return (
<div className="all-main-content">
<main>
<article className="intro-article">
<h2 className="article-title">SDG Announces Hackathon!</h2>
<p>
SDG announces the 2020 Summer Hackathon. Join us for an exciting
weekend
</p>
<a className="read-more" href="#here">
read more about SDG Announces Hackathon!
</a>
</article>
<article className="intro-article">
<h2 className="article-title">
Student Graduation is Right Around the Corner
</h2>
<p>
Our next cohort of students will be graduating in just over a week.
</p>
<a className="read-more" href="#here">
read more about Student Graduation is Right Around the Corner
</a>
</article>
</main>
</div>
)
}
export default App

class versus className

You may have noticed we used className= everywhere in the code instead of class=. This is because JSX uses the DOM names for properties whereas HTML uses a more generic name. In the DOM it is the className property that class= becomes. So we will be using className for our class names in JSX.

Don't worry, our console will warn us of these types of errors when we make them.

Some CSS to help

Let's use this CSS to make the app look better

@import url('https://fonts.googleapis.com/css2?family=Open+Sans&display=swap');
:root {
font: 16px / 1 sans-serif;
}
html {
height: 100%;
}
body {
font-family: 'Open Sans', sans-serif;
margin: 0;
min-height: 100%;
background-color: #f7f0da;
color: #2f3737;
}
article {
max-width: 20rem;
padding: 1rem 3rem;
font-size: 0.8rem;
}
article .read-more {
font-size: 0.6rem;
}
article h2 {
font-size: 1.5rem;
color: #5a9090;
}
main {
display: flex;
flex-wrap: wrap;
}
.read-more {
text-transform: uppercase;
font-size: 0.8rem;
font-weight: 800;
text-decoration: none;
}

Load this in the browser

We should see our two articles displayed.

Extracting common code into a "component"

Looking at our code we have two <article> elements that have the same structure. It would be nice to have one place in the code where we could define this structure and use code to dynamically create them with the correct customization.

Let's start that process.

Creating a NewsArticle component.

As we work on creating components it is a good practice to place the files in a components directory within the src directory. While this isn't required it is often considered best practices.

If your project doesn't already have a components directory, make one now.

Then create a new file in the components directory and name it NewsArticle.tsx. If you do not already have a components directory in your project, you should make one and then create NewsArticle.tsx inside.

We'll add this as the first line:

import React from 'react'

This line tells the script we are going to use React and it activates the JSX template process.

Next, we will make our component:

export function NewsArticle() {
// code here
}

the export at the beginning of that line, tells JavaScript we wish to share this class outside of the file. It also exports this function by name rather than as the default export. See the lesson on JavaScript modules for more on the difference between the two. We'll use the export in just a moment.

And we will ensure it has a render() method.

export function NewsArticle() {
return <div>Something</div>
}

Now let's see if we have a working component.

Using our new NewsArticle from the App

Returning to our App.tsx we can bring in this component to use. At the top, and at the end of the list of import we will add

import { NewsArticle } from './components/NewsArticle'

This line tells JavaScript we wish to use the NewsArticle component in this code, and that it can be found in the file NewsArticle.tsx in the components folder. Notice we do not add the extension. The import system is smart and can tell we mean the jsx version. If there were multiple files with the same extension we'd have to be more clear.

Finally, we can add this element to our App. Let's insert it right inside the <main>

<NewsArticle />

When reloading the browser we should see the <div>Something</div> in our content.

This means our NewsArticle component is rendering itself.

Composition

This is the idea of composition -- we are now defining a component, that has it's own content, embedded into another component, in this case the App.

Update the NewsArticle

Let's take one example of the news article we have and make it the method's JSX.

import React from 'react'
export function NewsArticle() {
return (
<article className="intro-article">
<h2 className="article-title">
Student Graduation is Right Around the Corner
</h2>
<p>Our next cohort of students will be graduating in just over a week.</p>
<a className="read-more" href="#here">
read more about Student Graduation is Right Around the Corner
</a>
</article>
)
}

You should notice that our app now has THREE articles. The first comes from our <NewsArticle/> and the other two from the hardcoded elements.

Let's remove the other two hardcoded <article>s leaving only our <NewsArticle/>

import React from 'react'
import { NewsArticle } from './components/NewsArticle'
function App() {
return (
<div className="all-main-content">
<main>
<NewsArticle />
</main>
</div>
)
}
export default App

We should only see one article listed. If we repeat the <NewsArticle/> we can have as many of the <article> structure as we want.

import React from 'react'
import { NewsArticle } from './components/NewsArticle'
function App() {
return (
<div className="all-main-content">
<main>
<NewsArticle />
<NewsArticle />
<NewsArticle />
<NewsArticle />
</main>
</div>
)
}
export default App

This makes the article reusable. However, it is not yet customizable. It would be nice to specify a different title and body for each article. Luckily there is a way to do that!

Component properties: props

We can add properties to our components by specifying them in a very similar way we would for regular HTML elements.

<NewsArticle
title="SDG Announces Hackathon!"
body="SDG announces the 2020 Summer Hackathon. Join us for an exciting weekend"
/>
<NewsArticle
title="Student Graduation is Right Around the Corner"
body="Our next cohort of students will be graduating in just over a week."
/>
<NewsArticle
title="SDG Standardizes on React"
body="React is the best library for learning front end Web"
/>

Here we are asking to render three <NewsArticle/> components and provide each a different set of properties or in React terms: props

This is great, however, our <NewsArticle> still shows the hardcoded data.

Using props in a component

When React places our component on the page and calls the method to generate the elements, it makes the supplied props available in the argument to the function. The props argument is an object whose keys are the names of the properties. In our case this is props.title and props.body -- the corresponding values are supplied as well.

When defining the props argument we need to define the types for this object. We will create a type named NewsArticleProps and declare that the title property shall be a string and the body property shall be a string as well. When defining the component function we'll declare that props has a type of NewsArticleProps

We can use these in our component by using an interpolation method within JSX. This is much like string interpolation in plain JavaScript but the syntax is slightly different:

import React from 'react'
type NewsArticleProps = {
title: string
body: string
}
export function NewsArticle(props: NewsArticleProps) {
return (
<article className="intro-article">
<h2 className="article-title">{props.title}</h2>
<p>{props.body}</p>
<a className="read-more" href="#here">
read more about {props.title}
</a>
</article>
)
}

Now when each of these components is rendered on the page, the unique values for props are available and we now have a component that is:

  • reusable
  • customizable

Driving our application from data

This is great, and we have an application that can render any number of articles we want. However, we still must manually code these in our main application.

import React from 'react'
import { NewsArticle } from './components/NewsArticle'
function App() {
return (
<div className="all-main-content">
<main>
<NewsArticle
title="sdg announces hackathon!"
body="sdg announces the 2020 summer hackathon. join us for an exciting weekend"
/>
<NewsArticle
title="student graduation is right around the corner"
body="our next cohort of students will be graduating in just over a week."
/>
<NewsArticle
title="sdg standardizes on react"
body="reactjs is the best library for learning front end web"
/>
</main>
</div>
)
}
export default App

It would be nice to render this from the data.

Importing JSON data

Let's start by making a JSON file named articles.json in the directory along with App.tsx -- In this file, we will describe, in JSON, an array of articles we want to render. We will also give each article an id as if it came from an API since that is likely the most common case for where this data will eventually come from.

[
{
"id": 42,
"title": "SDG Announces Hackathon!",
"body": "SDG announces the 2020 Summer Hackathon. Join us for an exciting weekend"
},
{
"id": 99,
"title": "Student Graduation is Right Around the Corner",
"body": "Our next cohort of students will be graduating in just over a week."
},
{
"id": 100,
"title": "SDG Standardizes on React",
"body": "React is the best library for learning front end Web"
},
{
"id": 101,
"title": "This data comes from JSON!",
"body": "React works with data using tools we already know!"
}
]

We will be using this in our App.tsx so let's import it!

import React from 'react'
import { NewsArticle } from './components/NewsArticle'
import articles from './articles.json'
function App() {
return (
<div className="all-main-content">
<main>
<NewsArticle
title="sdg announces hackathon!"
body="sdg announces the 2020 summer hackathon. join us for an exciting weekend"
/>
<NewsArticle
title="student graduation is right around the corner"
body="our next cohort of students will be graduating in just over a week."
/>
<NewsArticle
title="sdg standardizes on react"
body="reactjs is the best library for learning front end web"
/>
</main>
</div>
)
}
export default App

The line import articles from './articles.json' will read the JSON file and make its contents available as the variable articles! No parsing required! This is because the environment comes with a loader for JSON files and it knows how to read and parse them for us!

Let's use that data to build up an array of <NewsArticle/> components.

Transforming data into components

Since we want one <NewsArticle/> that is related to each element of the articles array, we will bring out our friend map

import React from 'react'
import { NewsArticle } from './components/NewsArticle'
import articles from './articles.json'
function App() {
const newsArticlesFromData = articles.map(article => (
<NewsArticle title={article.title} body={article.body} />
))
return (
<div className="all-main-content">
<main>
<NewsArticle
title="sdg announces hackathon!"
body="sdg announces the 2020 summer hackathon. join us for an exciting weekend"
/>
<NewsArticle
title="student graduation is right around the corner"
body="our next cohort of students will be graduating in just over a week."
/>
<NewsArticle
title="sdg standardizes on react"
body="reactjs is the best library for learning front end web"
/>
</main>
</div>
)
}
export default App

Breaking it down

Let's examine this critical line of code:

const newsArticlesFromData = articles.map(article => (
<NewsArticle title={article.title} body={article.body} />
))

In our [lesson on JavaScript iteration](/lessons/js-iteration] we demonstrated that map can turn an array of one type of element (say a JavaScript object in this case) into an array of another type of element, (

in this case)

So what is happening here is a transformation from the first array to the second.

NOTE: We shortened the strings for formatting purposes only

[
{
"id": 42,
"title": "SDG Announces ...",
"body": "SDG announces ..."
},
{
"id": 99,
"title": "Student Graduation ...",
"body": "Our next cohort ..."
},
{
"id": 100,
"title": "SDG Standardizes ...",
"body": "React is the ..."
},
{
"id": 101,
"title": "This data ...",
"body": "React works ..."
}
]
[
<NewsArticle title="SDG Announces ..." body="SDG announces ..." />,
<NewsArticle title="Student Graduation ..." body="Our next cohort ..." />,
<NewsArticle title="SDG Standardizes ..." body="React is the ..." />,
<NewsArticle title="This data ..." body="React works ..." />,
]

Since we now have an array of the <NewsArticle/> we can simply place them where we want them in place of the hardcoded data.

import React from 'react'
import { NewsArticle } from './components/NewsArticle'
import articles from './articles.json'
function App() {
const newsArticlesFromData = articles.map(article => (
<NewsArticle title={article.title} body={article.body} />
))
return (
<div className="all-main-content">
<main>{newsArticlesFromData}</main>
</div>
)
}
export default App

NOTE: We don't even have to do anything special with the array to get it to output since JSX already knows how to deal with arrays, it just outputs each element as if we had hardcoded it.

There is one other thing we need to do. If you look in your console you will see a message about each element needing a key. There is another React rule that is important to know.

RULE: Each component that is rendered dynamically from an array of data must have a unique key. That key must only be unique for that array of data. (i.e. that same key can be in another array-to-component map in another part of the app, but must be unique for this array)

Well, now it is handy that we had that id attribute of our JSON objects!

import React from 'react'
import { NewsArticle } from './components/NewsArticle'
import articles from './articles.json'
function App() {
const newsArticlesFromData = articles.map(article => (
<NewsArticle key={article.id} title={article.title} body={article.body} />
))
return (
<div className="all-main-content">
<main>{newsArticlesFromData}</main>
</div>
)
}
export default App

The key prop is a special property and is used by React only. We don't use it with our NewsArticle component. In a later lesson, we will learn why this key is so important.

Conclusion

We now have an application that allows us to add more articles to this listing. If we add new data to our JSON file and reload the application it reacts to the new data by rendering more information.

In the following lessons, we will learn how to load data from a remote API, how to respond to events, how to update data dynamically, and how to add different "pages" to our application and give it the ability to navigate between them.

© 2017 - 2021; Built with ♥ in St. Petersburg, Florida.