React Tutorial An Overview and Walkthrough
React Tutorial An Overview and Walkthrough
taniarascia.com/getting-started-with-react
I tried to condense everything I've learned into a nice introduction to share with you, so
here it is.
Prerequisites
There are a few things you should know in advance before you start playing around with
React. If you've never used JavaScript or the DOM at all before, for example, I would get
more familiar with those before trying to tackle React.
Goals
Learn about essential React concepts and related terms, such as Babel, Webpack,
JSX, components, props, state, and lifecycle.
Build a very simple React app that demonstrates the above concepts.
What is React?
React is a JavaScript library - one of the most popular ones, with over 100,000 stars
on GitHub.
React is not a framework (unlike Angular, which is more opinionated).
1/26
React is an open-source project created by Facebook.
React is used to build user interfaces (UI) on the front end.
React is the view layer of an MVC application (Model View Controller)
One of the most important aspects of React is the fact that you can create components,
which are like custom, reusable HTML elements, to quickly and efficiently build user
interfaces. React also streamlines how data is stored and handled, using state and
props.
We'll go over all of this and more throughout the article, so let's get started.
Let's start by making a basic index.html file. We're going to load in three CDNs in the
head - React, React DOM, and Babel. We're also going to make a div with an id called
root , and finally we'll create a script tag where your custom code will live.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello React!</title>
<script src="https://unpkg.com/react@^16/umd/react.production.min.js">
</script>
<script src="https://unpkg.com/[email protected]/umd/react-
dom.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/babel.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// React code will go here
</script>
</body>
</html>
I'm loading in the latest stable versions of the libraries as of the time of this writing.
2/26
React - the React top level API
React DOM - adds DOM-specific methods
Babel - a JavaScript compiler that lets us use ES6+ in old browsers
The entry point for our app will be the root div element, which is named by convention.
You'll also notice the text/babel script type, which is mandatory for using Babel.
Now, let's write our first code block of React. We're going to use ES6 classes to create a
React component called App .
index.html
Now we'll add the render() method, the only required method in a class component,
which is used to render DOM nodes.
index.html
Inside the return , we're going to put what looks like a simple HTML element. Note that
we're not returning a string here, so don't use quotes around the element. This is called
JSX , and we'll learn more about it soon.
index.html
Finally, we're going to use the React DOM render() method to render the App class
we created into the root div in our HTML.
index.html
index.html
3/26
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello React!</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js">
</script>
<script src="https://unpkg.com/[email protected]/babel.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class App extends React.Component {
render() {
return <h1>Hello world!</h1>
}
}
Now if you view your index.html in the browser, you'll see the h1 tag we created
rendered to the DOM.
Cool! Now that you've done this, you can see that React isn't so insanely scary to get
started with. It's just some JavaScript helper libraries that we can load into our HTML.
4/26
We've done this for demonstration purposes, but from here out we're going to use another
method: Create React App.
Fortunately, Facebook has created Create React App, an environment that comes pre-
configured with everything you need to build a React app. It will create a live development
server, use Webpack to automatically compile React, JSX, and ES6, auto-prefix CSS files,
and use ESLint to test and warn about mistakes in the code.
To set up create-react-app , run the following code in your terminal, one directory up
from where you want the project to live.
Once that finishes installing, move to the newly created directory and start the project.
Once you run this command, a new window will popup at localhost:3000 with your
new React app.
Create React App is very good for getting started for beginners as well as large-scale
enterprise applications, but it's not perfect for every workflow. You can also create your own
Webpack setup for React.
5/26
If you look into the project structure, you'll see a /public and /src directory, along
with the regular node_modules , .gitignore , README.md , and package.json .
In /public , our important file is index.html , which is very similar to the static
index.html file we made earlier - just a root div. This time, no libraries or scripts are
being loaded in. The /src directory will contain all our React code.
To see how the environment automatically compiles and updates your React code, find
the line that looks like this in /src/App.js :
And replace it with any other text. Once you save the file, you'll notice localhost:3000
compiles and refreshes with the new data.
Go ahead and delete all the files out of the /src directory, and we'll create our own
boilerplate file without any bloat. We'll just keep index.css and index.js .
For index.css , I just copy-and-pasted the contents of Primitive CSS into the file. If you
want, you can use Bootstrap or whatever CSS framework you want, or nothing at all. I just
find it easier to work with.
Now in index.js , we're importing React, ReactDOM, and the CSS file.
src/index.js
Let's create our App component again. Before, we just had an <h1> , but now I'm
adding in a div element with a class as well. You'll notice that we use className instead
of class . This is our first hint that the code being written here is JavaScript, and not
actually HTML.
src/index.js
src/index.js
6/26
Here's our full index.js . This time, we're loading the Component as a property of
React, so we no longer need to extend React.Component .
src/index.js
If you go back to localhost:3000 , you'll see "Hello, React!" just like before. We have
the beginnings of a React app now.
There is an extension called React Developer Tools that will make your life much easier
when working with React. Download React DevTools for Chrome, or whatever browser
you prefer to work on.
After you install it, when you open DevTools, you'll see a tab for React. Click on it, and
you'll be able to inspect components as they're written. You can still go to the Elements
tab to see the actual DOM output. It may not seem like that much of a deal now, but as the
app gets more complicated, it will become increasingly necessary to use.
7/26
Now we have all the tools and setup we need to actually begin working with React.
With JSX, we can write what looks like HTML, and also we can create and use our own
XML-like tags. Here's what JSX looks like assigned to a variable.
JSX
Using JSX is not mandatory for writing React. Under the hood, it's running
createElement , which takes the tag, object containing the properties, and children of
the component and renders the same information. The below code will have the same
output as the JSX above.
No JSX
JSX is actually closer to JavaScript, not HTML, so there are a few key differences to note
when writing it.
8/26
Self-closing tags must end in a slash - e.g. <img />
JavaScript expressions can also be embedded inside JSX using curly braces, including
variables, functions, and properties.
JSX is easier to write and understand than creating and appending many elements in
vanilla JavaScript, and is one of the reasons people love React so much.
Components
So far, we've created one component - the App component. Almost everything in React
consists of components, which can be class components or simple components.
Most React apps have many small components, and everything loads into the main App
component. Components also often get their own file, so let's change up our project to do
so.
src/index.js
We'll create a new file called App.js and put the component in there.
src/App.js
We export the component as App and load it in index.js . It's not mandatory to
separate components into files, but an application will start to get unwieldy and out-of-
hand if you don't.
Class Components
9/26
Let's create another component. We're going to create a table. Make Table.js , and fill it
with the following data.
src/Table.js
src/App.js
Then by loading it into the render() of App , where before we had "Hello, React!". I
also changed the class of the outer container.
src/App.js
10/26
import React, {Component} from 'react'
import Table from './Table'
If you check back on your live environment, you'll see the Table loaded in.
Now we've seen what a custom class component is. We could reuse this component over
and over. However, since the data is hard-coded into it, it wouldn't be too useful at the
moment.
Simple Components
The other type of component in React is the simple component, which is a function.
This component doesn't use the class keyword. Let's take our Table and make two
simple components for it - a table header, and a table body.
We're going to use ES6 arrow functions to create these simple components. First, the
table header.
src/Table.js
11/26
const TableHeader = () => {
return (
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
)
}
src/Table.js
Now our Table file will look like this. Note that the TableHeader and TableBody
components are all in the same file, and being used by the Table class component.
src/Table.js
12/26
Everything should appear as it did before. As you can see, components can be nested in
other components, and simple and class components can be mixed.
A class component must include render() , and the return can only return one parent
element.
Simple Component
Class Component
Note that if the return is contained to one line, it does not need parentheses.
Props
Right now, we have a cool Table component, but the data is being hard-coded. One of
the big deals about React is how it handles data, and it does so with properties, referred to
as props, and with state. Now, we'll focus on handling data with props.
First, let's remove all the data from our TableBody component.
src/Table.js
Then let's move all that data to an array of objects, as if we were bringing in a JSON-based
API. We'll have to create this array inside our render() .
src/App.js
13/26
class App extends Component {
render() {
const characters = [
{
name: 'Charlie',
job: 'Janitor',
},
{
name: 'Mac',
job: 'Bouncer',
},
{
name: 'Dee',
job: 'Aspring actress',
},
{
name: 'Dennis',
job: 'Bartender',
},
]
return (
<div className="container">
<Table />
</div>
)
}
}
Now, we're going to pass the data through to the child component ( Table ) with
properties, kind of how you might pass data through using data- attributes. We can call
the property whatever we want, as long as it's not a reserved keyword, so I'll go with
characterData . The data I'm passing through is the characters variable, and I'll put
curly braces around it as it's a JavaScript expression.
src/App.js
return (
<div className="container">
<Table characterData={characters} />
</div>
)
Now that data is being passed through to Table , we have to work on accessing it from
the other side.
src/Table.js
14/26
class Table extends Component {
render() {
const {characterData} = this.props
return (
<table>
<TableHeader />
<TableBody characterData={characterData} />
</table>
)
}
}
If you open up React DevTools and inspect the Table component, you'll see the array of
data in the property. The data that's stored here is known as the virtual DOM, which is a
fast and efficient way of syncing data with the actual DOM.
This data is not in the actual DOM yet, though. In Table , we can access all props
through this.props . We're only passing one props through, characterData, so we'll use
this.props.characterData to retrieve that data.
I'm going to use the ES6 property shorthand to create a variable that contains
this.props.characterData .
Since our Table component actually consists of two smaller simple components, I'm
going to pass it through to the TableBody , once again through props.
src/Table.js
15/26
class Table extends Component {
render() {
const {characterData} = this.props
return (
<table>
<TableHeader />
<TableBody characterData={characterData} />
</table>
)
}
}
src/Table.js
We're going to pass the props through as a parameter, and map through the array to
return a table row for each object in the array. This map will be contained in the rows
variable, which we'll return as an expression.
src/Table.js
return <tbody>{rows}</tbody>
}
If you view the front end of the app, all the data is loading in now.
You'll notice I've added a key index to each table row. You should always use keys when
making lists in React, as they help identify each list item. We'll also see how this is
necessary in a moment when we want to manipulate list items.
Props are an effective way to pass existing data to a React component, however the
component cannot change the props - they're read-only. In the next section, we'll learn
how to use state to have further control over handling data in React.
State
16/26
Right now, we're storing our character data in an array in a variable, and passing it
through as props. This is good to start, but imagine if we want to be able to delete an item
from the array. With props, we have a one way data flow, but with state we can update
private data from a component.
You can think of state as any data that should be saved and modified without necessarily
being added to a database - for example, adding and removing items from a shopping cart
before confirming your purchase.
src/App.js
The object will contain properties for everything you want to store in the state. For us, it's
characters .
src/App.js
src/App.js
Our data is officially contained in the state. Since we want to be able to remove a character
from the table, we're going to create a removeCharacter method on the parent App
class.
To retrieve the state, we'll get this.state.characters using the same ES6 method as
before. To update the state, we'll use this.setState() , a built-in method for
manipulating state. We'll filter the array based on an index that we pass through, and
return the new array.
17/26
You must use this.setState() to modify an array. Simply applying a new value to
this.state.property will not work.
src/App.js
this.setState({
characters: characters.filter((character, i) => {
return i !== index
}),
})
}
filter does not mutate but rather creates a new array, and is a preferred method for
modifying arrays in JavaScript. This particular method is testing an index vs. all the
indices in the array, and returning all but the one that is passed through.
Now we have to pass that function through to the component, and render a button next to
each character that can invoke the function. We'll pass the removeCharacter function
through as a prop to Table .
src/App.js
render() {
const { characters } = this.state
return (
<div className="container">
<Table characterData={characters} removeCharacter={this.removeCharacter} />
</div>
)
}
Since we're passing it down to TableBody from Table , we're going to have to pass it
through again as a prop, just like we did with the character data.
In addition, since it turns out that the only components having their own states in our
project are App and Form , it would be best practice to transform Table into a simple
component from the class component it currently is.
src/Table.js
return (
<table>
<TableHeader />
<TableBody characterData={characterData} removeCharacter={removeCharacter}
/>
</table>
)
}
18/26
Here's where that index we defined in the removeCharacter() method comes in. In the
TableBody component, we'll pass the key/index through as a parameter, so the filter
function knows which item to remove. We'll create a button with an onClick and pass it
through.
src/Table.js
<tr key={index}>
<td>{row.name}</td>
<td>{row.job}</td>
<td>
<button onClick={() => props.removeCharacter(index)}>Delete</button>
</td>
</tr>
The onClick function must pass through a function that returns the
removeCharacter() method, otherwise it will try to run automatically.
Awesome. Now we have delete buttons, and we can modify our state by deleting a
character.
I deleted Mac.
Now you should understand how state gets initialized and how it can be modified.
Before anything else, let's remove all the hard-coded data from state.characters , as
we'll be updating that through the form now.
19/26
src/App.js
Now let's go ahead and create a Form component in a new file called Form.js .
We're going to set the initial state of the Form to be an object with some empty
properties, and assign that initial state to this.state .
src/Form.js
state = this.initialState
}
Our goal for this form will be to update the state of Form every time a field is changed in
the form, and when we submit, all that data will pass to the App state, which will then
update the Table .
First, we'll make the function that will run every time a change is made to an input. The
event will be passed through, and we'll set the state of Form to have the name (key)
and value of the inputs.
src/Form.js
this.setState({
[name]: value,
})
}
Let's get this working before we move on to submitting the form. In the render, let's get
our two properties from state, and assign them as the values that correspond to the
proper form keys. We'll run the handleChange() method as the onChange of the
input, and finally we'll export the Form component.
src/Form.js
20/26
render() {
const { name, job } = this.state;
return (
<form>
<label htmlFor="name">Name</label>
<input
type="text"
name="name"
id="name"
value={name}
onChange={this.handleChange} />
<label htmlFor="job">Job</label>
<input
type="text"
name="job"
id="job"
value={job}
onChange={this.handleChange} />
</form>
);
}
src/App.js
src/App.js
return (
<div className="container">
<Table characterData={characters} removeCharacter={this.removeCharacter} />
<Form />
</div>
)
Now if we go to the front end of our app, we'll see a form that doesn't have a submit yet.
Update some fields and you'll see the local state of Form being updated.
21/26
Cool. Last step is to allow us to actually submit that data and update the parent state.
We'll create a function called handleSubmit() on App that will update the state by
taking the existing this.state.characters and adding the new character
parameter, using the ES6 spread operator.
src/App.js
Now in Form , we'll create a method called submitForm() that will call that function,
and pass the Form state through as the character parameter we defined earlier. It will
also reset the state to the initial state, to clear the form after submit.
src/Form.js
submitForm = () => {
this.props.handleSubmit(this.state)
this.setState(this.initialState)
}
Finally, we'll add a submit button to submit the form. We're using an onClick instead of
an onSubmit since we're not using the standard submit functionality. The click will call
the submitForm we just made.
And that's it! The app is complete. We can create, add, and remove users from our table.
Since the Table and TableBody were already pulling from the state, it will display
properly.
22/26
If you got lost anywhere along the way, you can view the complete source on GitHub.
As a little test, we can create a new Api.js file, and create a new App in there. A public
API we can test with is the Wikipedia API, and I have a URL endpoint right here for a
random* search. You can go to that link to see the API - and make sure you have
JSONView installed on your browser.
We're going to use JavaScript's built-in Fetch to gather the data from that URL endpoint
and display it. You can switch between the app we created and this test file by just
changing the URL in index.js - import App from './Api'; .
I'm not going to explain this code line-by-line, as we've already learned about creating a
component, rendering, and mapping through a state array. The new aspect to this code is
componentDidMount() , a React lifecycle method. Lifecycle is the order in which
methods are called in React. Mounting refers to an item being inserted into the DOM.
Api.js
23/26
import React, {Component} from 'react'
// Code is invoked after the component is mounted/inserted into the DOM tree.
componentDidMount() {
const url =
'https://en.wikipedia.org/w/api.php?
action=opensearch&search=Seona+Dancing&format=json&origin=*'
fetch(url)
.then((result) => result.json())
.then((result) => {
this.setState({
data: result,
})
})
}
render() {
const {data} = this.state
return <ul>{result}</ul>
}
}
Once you save and run this file in the local server, you'll see the Wikipedia API data
displayed in the DOM.
There are other lifecycle methods, but going over them will be beyond the scope of this
article. You can read more about React components here.
24/26
*Wikipedia search choice may not be random. It might be an article that I spearheaded
back in 2005.
Now, if you just want to compile all the React code and place it in the root of a directory
somewhere, all you need to do is run the following line:
This will create a build folder which will contain your app. Put the contents of that
folder anywhere, and you're done!
We can also take it a step further, and have npm deploy for us. We're going to build to
GitHub pages, so you'll already have to be familiar with Git and getting your code up on
GitHub.
Make sure you've exited out of your local React environment, so the code isn't currently
running. First, we're going to add a homepage field to package.json , that has the URL
we want our app to live on.
package.json
"homepage": "https://taniarascia.github.io/react-tutorial",
"scripts": {
// ...
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
}
We'll create the build , which will have all the compiled, static files.
25/26
Conclusion
This article should have given you a good introduction to React, simple and class
components, state, props, working with form data, pulling data in from an API, and
deploying an app. There is much more to learn and do with React, but I hope you feel
confident delving in and playing around with React yourself now.
Please let me know if anything was unclear, or if there's anything else you'd like to see in
this or a subsequent article.
Comments
26/26