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
PascalCasestyle. - It must be a function (
functionstyle 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. Thatkeymust 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.