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 is 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 a 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 excitingweekend</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 practice.
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
its 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>
structures 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.
<NewsArticletitle="SDG Announces Hackathon!"body="SDG announces the 2020 Summer Hackathon. Join us for an exciting weekend"/><NewsArticletitle="Student Graduation is Right Around the Corner"body="Our next cohort of students will be graduating in just over a week."/><NewsArticletitle="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: stringbody: 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><NewsArticletitle="sdg announces hackathon!"body="sdg announces the 2020 summer hackathon. join us for an exciting weekend"/><NewsArticletitle="student graduation is right around the corner"body="our next cohort of students will be graduating in just over a week."/><NewsArticletitle="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><NewsArticletitle="sdg announces hackathon!"body="sdg announces the 2020 summer hackathon. join us for an exciting weekend"/><NewsArticletitle="student graduation is right around the corner"body="our next cohort of students will be graduating in just over a week."/><NewsArticletitle="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 is 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><NewsArticletitle="sdg announces hackathon!"body="sdg announces the 2020 summer hackathon. join us for an exciting weekend"/><NewsArticletitle="student graduation is right around the corner"body="our next cohort of students will be graduating in just over a week."/><NewsArticletitle="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, 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 (
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
. Thatkey
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.