This is an easily digestable guide for those who would like to get a React application up and running quickly mixed with production considerations
Setup
Dependencies
Installing node and NPM
$ sudo apt-get update
$ sudo apt-get install nodejs
$ sudo apt-get install npm
If there are any problems follow this link here
Explanation: Node is a runtime environment for Javascript (allows you to run javascript code), NPM short for node package manager basically allows for easy access and updates of code modules (packages). More about npm
Project Initialization and NPM modules
Package to create react app template
$ npm install -g create-react-app
The create-react-app
package allows one to create a working template of a react app.
The app contains the following dependencies (other packages/modules)
react
- essential to build a react app
react-dom
- essential to built a react app
react-scripts
- used to run the application in your browser for testing and debugging
You can create the sample application by running
$ create-react-app sample-app
Here I used "sample-app" as the name of my application you can use whatever your like.
You can test the application by navigating to the root directory for the application e.g. "sample-app" and running
$ npm start
The browser should open to the application running on localhost:3000
Fresh Start
Restructuring
We want to start from nothing so we're going to remove all the previous code, remove all the current files from the src folder.
$ rm -rf src/*
In the src
folder Create two new files index.html
and index.js
We're going to create a basic web page and link the javascript file.
<!DOCTYPE html>
<html>
<head>
<title> MySite :) </title>
</head>
<body>
</body>
<script type="text/javascript" src="index.js"></script>
</html>
React Basics
Components I
What is React ?
There are very many fanciful and technical definitions which you can google, for now i'll say it in a simple manner using my own words
React is a framework that specializes on building an application using reuseable parts called Components that you create and customize.
What is a component ?
Components are the building blocks for react
A component can be thought of as a custom element that you create, for a simple example, consider the following
<h1> Bork Bork, I am hungry </h1>
Suppose we wanted to create an 'element' that would always do this, well that's where components come in, we can create a component to do just that.
In your index.js
file, insert the following.
import React,{Component} from 'react';
class Dog extends Component{
render(){
return(<h1>Bork Bork, I am hungry</h1>);
}
}
React
is the entry point to the React library. If you load React from a<script>
tag, these top-level APIs are available on theReact
global. If you use ES6 with npm, you can writeimport React from 'react'
. If you use ES5 with npm, you can writevar React = require('react').
- React docs
To put it simply, the React
library allows you to use Components
which gives you the ability to create 'custom elements' that you can reuse.
The Component
class's fundamental method is render
. Simply, the render
method should return what you would like on your page.
render, render ? React-Dom
Up till now we haven't actually put anything onto our page, it's time to change that, using React-Dom
. React-Dom
as the name implies, allows us to interact with the DOM. The bread and butter of this library is it's own render
method, which actually puts whatever is given to it on the page. The previous render
method was part of the Component
class and acted as the output for that specific Component
while this render
method takes whatever is given to it and spits it on the page wherever you specify.
Let's see how it works, first we need to create a place to put our component so we're going to add a div
with the id root, edit your index.html
to look like the following
<!DOCTYPE html>
<html>
<head>
<title> MySite :) </title>
</head>
<body>
<div id="root"> </div>
</body>
<script type="text/javascript" src="index.js"></script>
</html>
Now we're going to import the render
function from the react-dom
library and render
it in the div we just added, edit your index.js
to look like the following
import React,{Component} from 'react';
import {render} from 'react-dom';
class Dog extends Component{
render(){
return(<h1>Bork Bork, I am hungry</h1>);
}
}
render(<Dog/>, document.getElementById('root'));
Note that either render function must only have a single root element.
If you do not already have your application running you can do so by running
$ npm start
The browser should open to the application running on localhost:3000
Side step into JSX ?
It may seem confusing to see HTML code in your javascript file, this is because we are using JSX.
JSX is a preprocessor step that adds XML syntax to JavaScript.JSX allows you to naturally add HTML structure through javascript. (note we can use react without JSX however it's not the best idea imo)
- React docs
JSX allows you embed expressions i.e. put in javascript variables and manipulate them in the HTML. You can do this with the use of curly braces
{ }
import React,{Component} from 'react';
import {render} from 'react-dom';
class Dog extends Component{
render(){
let speech = "Bork Bork, I am hungry";
return(<h1>{speech}</h1>);
}
}
render(<Dog/>, document.getElementById('root'));
Try changing the text for speech to see if it works :^)
Components II
State mate
state
is an object that stores the state of a component and is defined in it's constructor
method. You can access it by conventional methods.
In the following, we are going to define speech
in the Component's state
and give it the text we'd like displayed.
import React,{Component} from 'react';
import {render} from 'react-dom';
class Dog extends Component{
constructor(){
super();
this.state = {
speech: "Bork Bork, I am a doggie :)"
}
}
render(){
return(<h1>{this.state.speech}</h1>);
}
}
render(<Dog/>, document.getElementById('root'));
Things to note, you should call super();
at the start of your constructor, it allows acces of props
state
is simple javascript object and speech
is just a property.
The way we accessed speech
was this.state.speech
Props man
props
are the properties you want to pass to your Component
. There are a few ways in which people pass props
however the fundamental principle is that a prop
is passed to a Component
as an attribute.
In the following example I am going to pass what I would the Dog Component
is going to say using a prop
that I will name woof
.
import React,{Component} from 'react';
import {render} from 'react-dom';
class Dog extends Component{
constructor(props){
super();
this.state = {
speech: props.woof
}
}
render(){
return(<h1>{this.state.speech}</h1>);
}
}
render(<Dog woof="Bork Bork, I am a good doggie :)"/>, document.getElementById('root'));
Things to note;
We passed in what our doggo is saying using the attribute woof <Dog woof="Bork Bork, I am a good doggie :)"/>
The constructor method accepted props
constructor(props)
props
is a simple object and woof is just a property accessed as usual props.woof
Updating state
We update a Component's state
using the setState
method. "Why can't we just set the state directly ?", well the setState
method has triggers that cause the component to be re-rendered for the new values. To put it simply, if we use setState
the component is automatically updated for us in the DOM.
To show how this works, we're going to create an input box that allows us to update text for our Dog
Component. We're going to (1) add an input box, (2) define some function to update the state
with the text from the box.
import React,{Component} from 'react';
import {render} from 'react-dom';
class Dog extends Component{
constructor(props){
super();
this.state = {
speech: props.woof,
}
}
textChanged = (e) =>{
this.setState({speech:e.target.value})
}
render(){
return(
<div>
<h1>{this.state.speech}</h1>
<input onInput={this.textChanged} type="text"/>
</div>
);
}
}
render(<Dog woof="Bork Bork,I am a good doggie :)"/>, document.getElementById('root'));
We created a function textChanged
to update the state
's property speech
with whatever the user inputs. We also added an input
field and used it's onInput
attribute to call our textChanged
function, note that the input
element and the onInput
attribute are default HTML.
If you're paying attention, there is one more thing we changed, we put a div
around the h1
and input
tags. This is because there must be a single root element for the render
function.
A bit closer to the Standard
The usual way to do things; the entire application is usually one Component
using other smaller Components
that you create (which may use other smaller Components
that you create, compoception :o )
Okay spread em, we'll leave our index.js
for our main app component and put a the Dog
component in a new file Dog.js
.
Create Dog.js
and make it look like this
import React,{Component} from 'react';
export default class Dog extends Component{
constructor(props){
super();
this.state = {
speech: props.woof,
}
}
textChanged = (e) =>{
this.setState({speech:e.target.value})
}
render(){
return(
<div>
<h1>Bork Bork,{this.state.speech}</h1>
<input onInput={this.textChanged} type="text"/>
</div>
);
}
}
Now time for index.js
, we're going to create a new component to represent our app and we'll call it App
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
class App extends Component{
render(){
return(
<div>
<Dog woof="I need petting" />
</div>
);
}
}
render(<App/>, document.getElementById('root'));
Try to create a simple Cat
component on your own in a file Cat.js
, i'll put a sample below in case you're feeling a bit lazy =/.
import React, {Component} from 'react';
export default class Cat extends Component{
constructor(){
super();
}
render(){
return(
<h1> Meow :) </h1>
);
}
}
Now make the required edits to your index.js
file to import our Cat
component and render it
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
import Cat from './Cat.js';
class App extends Component{
render(){
return(
<div>
<Dog woof="I need petting" />
<Cat />
</div>
);
}
}
render(<App/>, document.getElementById('root'));
React Application Essentials
Routing
Installing react-router-dom
There is only one HTML page so how exactly does one present different views or give the illusion of 'pages', how do we go about routing different views based on user selections. The intuition is to have components that represents views (pages) and load components based off what the user selects.
To help us achieve this we are going to use a library called react-router-dom
. This is an external library to react therefore we need to download and add it to our project, we can do this using npm
npm install react-router-dom --save
BrowserRouter and Route
There are two main components to consider for routing however we'll only be focusing and using the Component BrowserRouter
. BrowserRouter
acts the mastermind behind your routing, since we're swapping components rather than loading pages, BrowserRouter tracks your 'location' and saves 'browsing history' within the application.
The BrowserRouter
swaps components and memorizes the order of swaps but how do we actually define the routes i.e. what path => what component, well the Route
component does exactly that.
We're going to define a route for our Dog
component and another for our Cat
component, edit your index.js
too look like the following
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
import Cat from './Cat.js';
import { BrowserRouter, Route, Link } from 'react-router-dom';
class App extends Component{
render(){
return(
<BrowserRouter>
<div>
<Route path="/dog" component={Dog}/>
<Route path="/cat" component={Cat}/>
</div>
</BrowserRouter>
);
}
}
render(<App/>, document.getElementById('root'));
We changed the components Dog
and Cat
with the Route
component. In the Route
component, we specified the path in the path
property and the component to load in the component
attribute, weird right ( ͡° ͜ʖ ͡°).
We then wrapped everything in the BrowserRouter
component, note that BrowserRouter
only expects a single child.
Run your application then navigate to localhost:3000/cat and localhost:3000/dog.
Links
Let's create a simple menu to link to our routes.
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
import Cat from './Cat.js';
import { BrowserRouter, Route, Link } from 'react-router-dom';
class App extends Component{
render(){
return(
<BrowserRouter>
<div>
<Route path="/dog" component={Dog}/>
<Route path="/cat" component={Cat}/>
<ul>
<li> <a href="/dog">dog</a> </li>
<li> <a href="/cat">cat</a> </li>
</ul>
</div>
</BrowserRouter>
);
}
}
render(<App/>, document.getElementById('root'));
This triggers a browser refresh each time a link is clicked, this is bad because we already have everything we need loaded, this means our application can run much faster. To solve this we replace the anchor tags with the Link
component. The Link
component acts just as the anchor tag would but without the page refresh.
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
import Cat from './Cat.js';
import { BrowserRouter, Route, Link } from 'react-router-dom';
class App extends Component{
render(){
return(
<BrowserRouter>
<div>
<Route path="/dog" component={Dog}/>
<Route path="/cat" component={Cat}/>
<ul>
<li> <Link to="/dog">dog</Link> </li>
<li> <Link to="/cat">cat</Link> </li>
</ul>
</div>
</BrowserRouter>
);
}
}
render(<App/>, document.getElementById('root'));
Routes++;
Take a look at our Dog
component, while everything does work, an initial statement is missing for our doggo. We've not passed in any woof
property. Let's look at our Route
component, we need to pass in more than just a bare component Dog
, for this we can use the render
property.
The render
property works similarly to the component
property in that it tells the Route
component what needs to be on the page however, the render
property allows more flexibility. The render
property accepts a function that must return what is to be rendered, meaning you can write and do whatever you like in that function.
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
import Cat from './Cat.js';
import { BrowserRouter, Route, Link } from 'react-router-dom';
class App extends Component{
render(){
return(
<BrowserRouter>
<div>
<Route path="/dog" render={
()=>{
return <Dog woof={"I can speak for myself"}/>
}
}/>
<Route path="/cat" component={Cat}/>
<ul>
<li> <Link to="/dog">dog</Link> </li>
<li> <Link to="/cat">cat</Link> </li>
</ul>
</div>
</BrowserRouter>
);
}
}
render(<App/>, document.getElementById('root'));
In our Route
component, we simply replaced the component
property with the render
property which accepts a function that returns something to be rendered. We wrote a function that returns our Dog
component with a woof
property and of course we wrapped that between curly braces.
We can tidy up a little for some more complexity, since the render property accepts a function, we can define a function outside and simply return that function.
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
import Cat from './Cat.js';
import { BrowserRouter, Route, Link } from 'react-router-dom';
class App extends Component{
render(){
let func = ()=>{
return(<Dog woof={"I can speak for myself"}/>);
}
return(
<BrowserRouter>
<div>
<Route path="/dog" render={func}/>
<Route path="/cat" component={Cat}/>
<ul>
<li> <Link to="/dog">dog</Link> </li>
<li> <Link to="/cat">cat</Link> </li>
</ul>
</div>
</BrowserRouter>
);
}
}
render(<App/>, document.getElementById('root'));
Now our func function is too small so we're gonna add some more stuff to justify pulling it out.
Simple Route Restriction
I only want authorized individuals to see my Dog
component, what should we do ? (secret doggo). Well to begin, we need something to indicate whether or not our user is authorized or not, for that we're going to add a property authorized
to our state. Then in our func
function, depending on if a user is authorized or not, we shall allow them to access our doggo.
Our func
function however SHOULD definitely return some sort of view, therefore we're going to create a simple AccessDenied
component to return if a user does not have access.
First our AccessDenied
component in AccessDenied.js
.
import React,{Component} from 'react';
export default class AccessDenied extends Component{
render(){
return(
<div>
<h1>Access Denied</h1>
<img src="http://www.free-icons-download.net/images/dog-icon-86470.png" alt="dog pic"/>
</div>
)
}
}
Now to modify our index.js
import React,{Component} from 'react';
import {render} from 'react-dom';
import Dog from './Dog.js';
import Cat from './Cat.js';
import AccessDenied from './AccessDenied.js';
import { BrowserRouter, Route, Link } from 'react-router-dom';
class App extends Component{
constructor(){
super();
this.state={
authorized:0
}
}
render(){
let func = ()=>{
if(this.state.authorized)
return(<Dog woof={"I can speak for myself"}/>);
else
return(<AccessDenied/>);
}
return(
<BrowserRouter>
<div>
<Route path="/dog" render={func}/>
<Route path="/cat" component={Cat}/>
<ul>
<li> <Link to="/dog">dog</Link> </li>
<li> <Link to="/cat">cat</Link> </li>
</ul>
</div>
</BrowserRouter>
);
}
}
render(<App/>, document.getElementById('root'));
(Note: There are more complex ways to do this but for now this is effective and simple.)
Requests
Choosing a library
React
has no native way to make requests, therefore we need to use a javascript library to make these requests for us. There are several options, just to give some context, two of the most popular would be an old but gold JQuery
and one of the more popular newer guys fetch
, we'll be using neither ( ͡° ͜ʖ ͡°). We shall be using one of the middle-age guys axios
which is very popular and powerful.
Let's install axios
npm install axios --save
We'll just be making simple requests as there are many better tutorials that focus solely on axios, now let's look at some of the syntax
axios.get(url) //url of resource you're trying to get
.then(function(response){ //function to handle a successful response from the server
}).catch(function(err){ //function to handle a unsuccessful response from the server
})
Let's grab a simple json file from on the server and print it to console, you can put the following code at the buttom of your index.js then remove it after testing it out
axios.get('https://steffanboodhoo.github.io/sample_data.json')
.then(function(resp){
console.log(resp)
})
Let's create one more component, List, in a file List.js. We're going to render a simple list with the data we fetch using axios.
import React,{Component} from 'react';
export default class List extends Component{
constructor(){
super();
this.state={
items:[]
}
}
render(){
return(
<div>
</div>
)
}
}
This is the basic skeleton where we define some state to be used later and return an empty div, now in the constructor we're going to load some data using axios.
import React,{Component} from 'react';
import axios from 'axios';
export default class List extends Component{
constructor(){
super();
this.state={
items:[]
}
axios.get('https://steffanboodhoo.github.io/sample_data.json')
.then((resp)=>{
this.setState({items:resp.data})
});
}
render(){
return(
<div>
</div>
)
}
}
We've imported the axios library and used it to fetch some data and update our state with it. Now we're going to use that data to create our list.
import React,{Component} from 'react';
import axios from 'axios';
export default class List extends Component{
constructor(){
super();
this.state={
items:[]
}
axios.get('https://steffanboodhoo.github.io/sample_data.json')
.then((resp)=>{
this.setState({items:resp.data})
});
}
render(){
let func = ()=>{
let elems = []
for(let i in this.state.items)
elems.push(<h1>{this.state.items[i].first_name}</h1>);
return elems;
}
return(<div>{func()}</div>)
}
}
Important things to note, React elements can be stored in variables e.g. let elem = <h1> doggo </h1>;
, these same elements can be used in rendering using the curly braces e.g. (<div>{elem}</div>
.
Using these two concepts, we were able to create a function func
to loop through the data and create an array of elements. We then called func
inbetween the div which returned a list of elements to be rendered.
At this point you should be able to link this component on your own with a route or otherwise, give it a shot :^(click me)
(Consider making the call in the containing component, App, then passing the data to be rendered in props then use array.map to create your list of elements)
Closing remarks
There are a lot more complex topics and methods to be covered, I may cover in a follow up (depending on time, feedback etc). I really enjoyed doing this, I tried to make is as easily digestable while covering practical methods and understanding. Anyways if you have gone though this, please let me know what you think and if there are any errors or what topics/projects/tools you'd like to see me do cao m8s