ReactJS project based training with Road Trip Planner App

In-depth introduction to ReactJS for beginners

From basics down to the nitty-gritty of ReactJS:

This article is divided into three -

  • This article talks about basic React Concepts crucial to start the what, whys, and how of ReactJS.
  • Then we’ll set up the project directory and environment
  • next one teaches basic react syntax to code reusable components using a hands-on project

What is React

React is a javascript library that lets you build a website with small isolated pieces called React components, like building legos.

Let's now break down the official definition of React

React is a declarative, efficient, and flexible JavaScript library for building user interfaces.

declarative: We use components to tell React what a particular part of UI should like on the screen. How it happens isn't our concern, react handles that for us.

efficient: You’ll see how React applications are so much more efficient than the ones created with vanilla javascript, detailed discussion in VDOM section.

flexible: React helps you build re-usable components, you can use react components inside traditional code without having to re-write the whole project, besides it is said to be flexible as you can use it for not only web but also to create mobile applications.

How it works

React basically handles the view layer of the application by following a Component-driven-development (CDD) which is the core idea of React application development.

It breaks the UI into a component hierarchy.

Composition and inheritance

See on Twitter for different sections and different components even can bring down to basic /atomic components for the profile picture or username

Features of React

JSX

 //syntax-1 to write React element 
const Heading = <h1>Create a new Trip</h1>
You see that in the above code a javascript variable is assigned an HTML element, now if you just learned basic HTML and javascript, you might think how come Javascript and HTML are on the same line of code? It isn’t HTML, it is JSX - Javascript, and XML, JSX is an extension to javascript,
  • which makes it easier to write UI logic inside Javascript,
  • and it also allows React to show useful error messages and warnings related to UI

Without JSX you would have to use a method React.createElement() and pass the typical HTML element into it as a string, for every element you want to create. For eg the above code is equivalent to

//syntax-2 to React element
const Heading = React.createElement(
  'h1',                    //type of HTML element
  {},                      //props - will be discussed
  'Create a new Trip'      //children can be anything like an HTML element or another React component or a String like in this case
)

React doesn’t want you to write JSX, it’s your choice to use any of the above methods but note that inherently JSX gets converted into calls to React.createElement(), which means ultimately syntax-1 gets converted into syntax-2

  • Embedding Javascript Expressions in JSX

    Many times you’ll want to use javascript inside JSX, like in this case - you’ve got a React element inside a JS variable called Heading, now suppose you want to render it inside a div,

    • you can do it curly braces { } (we’ll see more use cases in the project tutorial)
<div className="planning-board-header">
	{Heading} 
</div>

//is Equivalent to 

<div className="planning-board-header">
	<h1>Create a new Trip</h1> 
</div>

Virtual DOM

  • DOM

    You might know what DOM is, and if not, in simple terms the HTML doc structure (the webpage structure) is represented as DOM (document object model). It is a tree structure that represents the relationship between different HTML nodes or elements. It’s not a part of the javascript, but a part of the browser, and every browser has DOM APIs to help different programming languages interact with the DOM.

    So to make modifications to the web page, Javascript understands and interacts with this object known as DOM and does so by querying and updating it, using DOM APIs like document document.getElementById().

    The point is that after every single update made by JavaScript, DOM re-renders the entire webpage (which means it re-paints everything on the screen) on every little update. In this process, all querying and updating are light and fast javascript operations and thus cheap. But can you imagine the cost of a browser re-writing the entire page which involves re-calculating CSS and re-running javascript for each element whether it’s updated or not? It’s not just costly but also sounds highly inefficient.

  • VDOM

    This is where Virtual DOM comes into the picture. In short, the Virtual DOM will help you re-render only the elements that are updated.

    render: means to insert dom nodes inside the actual dom tree

    Virtual DOM is just a plain javascript object representing the actual DOM. All updates are made to this VDOM rather than the actual DOM, updating VDOM is cheaper because it doesn't write to the screen.

    How VDOM works?

    • On render, a virtual representation of the UI is stored as a tree-like data structure, using a javascript object, in the memory - which is called VDOM or a virtual DOM tree.
    • On any further update no matter how small, a new VDOM tree is generated, because it’s really cheap - just a plain javascript object remember?
    • Starting from the root node both of these VDOM trees are compared using the diffing algorithm, to see what elements have changed.
    • After the changes are concluded, a React library called ReactDOM ensures that actual DOM updates and re-renders only the changed elements. This process is called reconciliation.

VDOM DOM diagrams goes here

Fundamentals

Components

The isolated code chunks that a React UI is made up of, are called components. They are like reusable javascript functions, optionally accepting some input and returning the content (in form of React elements) to be rendered on the webpage.

To create a UI using this approach, we split the UI into independent units (components), once we have identified these units, we arrange them into a Component hierarchy. Components that appear within another component are called child components in the hierarchy, and this is how we identify the parent-child relationships among components (later we’ll see how useful it is to know these theoretical facts to put it all together).

Let’s see how to define components in React, think of it molding a stamp once and then using it any number of times to create the instances.

There are two ways in react you can define components:

Functional Component

Functional components are the easiest way to build a React component. They are just ES6 javascript functions,

  • following Pascal naming convention,
  • should always return a JSX element,
  • accepts input as something called props, more on that later

Let’s create a location component for our app,

function Location(props){
  return <div> Jaipur, India </div>;
}

Class Component

To create a class component we create an ES6 class extending React.Component by which JS understands that this is a component and not just a plain ES6 class. Class components are a little more complex to build than functional components with some extra features available to them. Class components should have a render method that returns a JSX element or null.

class Location extends React.Component{
constructor(props){}  //optional for now
render(){
  return <div> Jaipur, India </div>;
}
}

Creating and using component Instances

To make use of these components you have to create instances of them. For example, you might declare a Location component using a class or function once and for all, but you will have a number of Location instances on your running app, each showing a different location.

class Planning extends React.Component{
  return (
    <div>
      <Location/>
			<Location/>
			<Location/>
			<Location/>
    </div>
  );
}

Component Hierarchy Check: The planning component contains instances of the Location component, we can say Location is a child component of Planning.

Now, you might have noticed that all of the four Location instances inside Planning are going to show the same location, yes! because we hard-coded it while declaring the Location component.

This was to give you an idea of what the most basic React components look like. But you see, just like Location, in most cases, we have to render some sort of dynamic data on the screen using these components. Which means components have to hold and handle this data somehow.

Props and State

There are two ways to manage data in React components, which can directly impact the output of the component

  • To pass data from the parent to children component we use props
  • To manage data within a component we use state variables

Props

Attributes passed to JSX elements or component instances are called props, props is short for properties, and it is received as function parameters by a functional component, and as constructor parameters by a class component.

It is a javascript object that can be used directly using a dot operator or can also be destructured.

//using props with a dot operator
function Location(props) {
  return <div>{props.location_name}</div>;
}

//using props by destructuring
function Location({ location_name }) {
  return <div>{location_name}</div>;
}

class Planning extends React.Component {
  locations = ["Jaipur, Rajasthan", "Ajmer, Rajasthan", "Jodhpur, Rajasthan"];

  render() {
    return (
      <div>
        <Location location_name={this.locations[0]} />
        <Location location_name={this.locations[1]} />
        <Location location_name={this.locations[2]} />
        <Location location_name="Udaipur, Rajasthan" /> 
      </div>
    );
  }
}

Note that you can only pass props from parent to children and not otherwise, it is called unidirectional dataflow in react, we’ll explore this concept later.

State

These are the in-built javascript objects, they are used as variables declared within a function or class, but the catch here is that any change in state variable will trigger a re-render of the component, also you should always change the state variable using a specifically given method called setState.

Note that if you change a state directly by re-assigning, it won’t cause an error, but it will not trigger the re-render, which is the main purpose of using a state variable.

This might all sound confusing, so imagine in the above example user was entering the locations one by one and expecting them to show up on the page, which means whenever the user enters a new location, the whole Planning component would be re-rendered with a newly added location.

Let’s convert the locations into a state variable, for simplicity we’ll keep just one dynamic location.

function Location(props) {
  return <div>{props.location_name}</div>;
}
class Planning extends React.Component {
    constructor(props) { 
        super(props);
        this.state = { location: "Jaipur, Rajasthan"} // we assign have to assign the initial value here
    }
// this function has to be called in order to change the state variable and re-render the planning component with new location
// it will be used by user input onChange event handler
changeLocation(){
		this.setState({location: userInput})
}
  render() {
    return (
      <div>
        <Location location_name={this.state.location} />
      </div>
    );
  }
}

Inside a functional component, writing states looks different, a hook called useState is used to create and update state variable. So instead having all of your state variables inside this.state object, you’ll have a useState hook for each state variable. Like this,

const [input, setInput] = useState("");
const [inputDate, setInputDate] = useState("");
const [inputTime, setInputTime] = useState("");

How it works ?

useState accepts the initial value of the state, and returns an array of two things - the current state and the function that is used to update the current state. So here, we have one state updation method for every state variable which rewrites the state variable every time it gets updated, unlike class components, where this.stateUpdate merges the previous state with the new one.

//FUNCTION COMPONENT 
const [input, setInput] = useState("");
const [inputDate, setInputDate] = useState("");
const [inputTime, setInputTime] = useState("");
//state updation in functional component 
setInput("new location name");
setInputDate("new date");

//now the first two input state c