React_04

React_04

·

11 min read

I must say that we have been studying a lot of theoretical concepts up until now. But to understand React, we must do it by building projects and learning theory only as and when required. This approach is called project-based learning.

Our first project in this series will be a food-ordering app. You can name it anything you like, but I'll go ahead and call it Food House. Before we begin, I would like to mention that I don't care about the styling of the app, we can always style it by putting in some CSS or use a styling framework later. We are here to learn React, not CSS. Initially, our priority should be to structure the components and make sure that the logic works just fine without any bugs. Without further ado, let's begin:

The first step to building any project is planning.

"Action without planning is the cause of failure."

Structure of our app

/* 
Our Food App structure will look like this, 
  1) Header
      - Logo
      - Nav Items(right side)
      - Cart
  2) Body
      - Search bar
      - Restaurants List
          - Restaurant card
              - Image
              - Name
              - Rating
  3) Footer
      - Links
      - Copyrights

*/

Let's clear out our previous app.js file and simply put this inside it:

import React from "react";
import ReactDOM from "react-dom/client";

const Header = () => <h4>Header</h4>;

const Body = () => <h4>Body</h4>;

const Footer = () => <h4>Footer</h4>;

// AppLayout component to show: Header, Body, Footer
const AppLayout = () => {
  return (
    <React.Fragment>
      <Header />
      <Body />
      <Footer />
    </React.Fragment>
  );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<AppLayout />);

Let's begin with our header component, add some classes to the divs and add basic css to those classes.

const Header = () => (
  <div className="header">
    Title
    <div className="nav-items">
      <ul>
        <li>Home</li>
        <li>About</li>
        <li>Contact</li>
        <li>Cart</li>
      </ul>
    </div>
  </div>
);
/* Header CSS */
.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 10px;
  border: 1px solid black;
}

.nav-items > ul {
  list-style-type: none;
  display: flex;
}

.nav-items > ul > li {
  padding: 10px;
}

In place of the title, let's add a logo and make this title a seperate component with CSS. I've put the img tag for the logo inside an a tag so that it can be made a clickable that redirects to the homepage by using href="/". I borrowed the logo src from google-images.

const Title = () => (
  <a href="/">
    <img
      className="logo"
      src="https://foodhouse.co.th/wp-content/uploads/2019/01/foodhouse-18.jpg"
      alt="Food Fire Logo"
    />
  </a>
);

const Header = () => (
  <div className="header">
    <Title />
    <div className="nav-items">
      <ul>
        <li>Home</li>
        <li>About</li>
        <li>Contact</li>
        <li>Cart</li>
      </ul>
    </div>
  </div>
);
/* Logo CSS */
.logo {
  padding-left: 10px;
  width: 100px;
}

Our basic header component is now ready! Before building the body component, let's understand some concepts, maybe some of these questions are in your mind!

Is JSX mandatory for React?

JSX is an Extension Syntax that allows writing HTML and Javascript together easily in React and is used to create React elements. These elements are then rendered to the React DOM. Each JSX element is just to make the use of React easy and for calling React.createElement(component, props, …children) with less work. So, anything that is done with JSX can also be done with just plain JavaScript. JSX is not mandatory but is used for writing better and cleaner code instead of writing code using React.CreateElement.

Is ES6 mandatory for React?

ES6 is not mandatory for React but is highly recommendable. The latest projects created on React rely a lot on ES6. React uses ES6, and you should be familiar with some of the new features like Classes, Arrow Functions, and Variables(let, const). ES6 stands for ECMAScript 6. ECMAScript was created to standardize JavaScript, and ES6 is the 6th version of ECMAScript, it was published in 2015.

How can we write comments in JSX?

JSX comments are written as follows:

{/* */} - for single or multiline comments

{/* A JSX comment */}
{/* 
  Multi
  line
  JSX
  comment
*/}

What is <React.Fragment></React.Fragment> and <></>?

<React.Fragment></React.Fragment> is a feature in React that allows you to return multiple elements from a React component by allowing you to group a list of children without adding extra nodes to the DOM. <></> is the shorthand tag for React.Fragment. The only difference between them is that the shorthand version does not support the key attribute.

return (
        <React.Fragment>
            <Header />
            <Navigation />
            <Main />
            <Footer />
        </React.Fragment>
    );

return (
        <>
            <Header />
            <Navigation />
            <Main />
            <Footer />
        </>
    );

Let's continue building the Body component. For now, let's build a simple card for a restaurant with some dummy data that has a name, cuisines (as a list of cuisine strings), average rating and a cloudinary-hosted image URL (in the form of CLOUDINARY_BASE_URL and cloudinaryImageId).

const CLOUDINARY_BASE_URL = "https://res.cloudinary.com/swiggy/image/upload/fl_lossy,f_auto,q_auto,w_508,h_320,c_fill/";

const RestaurantCard = ({ name, cloudinaryImageId, cuisines, avgRating }) => {
  return (
    <div className="card">
      <img src={CLOUDINARY_BASE_URL + cloudinaryImageId} />
      <h2>{name}</h2>
      <h3>{cuisines.join(", ")}</h3>
      <h4>{`${avgRating} stars`}</h4>
    </div>
  );
};

const Body = () => {
  const data = {
    name: "Domino's Pizza",
    cloudinaryImageId: "bz9zkh2aqywjhpankb07",
    cuisines: ["Pizzas"],
    avgRating: "4.0",
  };
  return <RestaurantCard {...data} />;
};
/* Card CSS */
.card {
  width: 200px;
  border: 1px solid black;
  padding: 10px;
  margin: 10px;
}

.card > img {
  width: 100%;
}

For learning purposes, I've taken the above data and the dataset that I'll be using soon, from the network tab of the official Swiggy website.

In any food ordering app, you'll see multiple cards for restaurants but for now, we'll only be rendering one card to keep it simple. Anything which is present inside curly braces {} needs no further explanation as it is pure JavaScript.

You may be wondering, what is this way of writing { name, cloudinaryImageId, cuisines, avgRating }?

All these 4 variables are props that we destructured and passed inside the component using the spread operator ... like so:

<RestaurantCard {...data} />

If we had not used the spread operator above, we would have had to pass all the props individually like so:

<RestaurantCard 
   name={data.name}
   cloudinaryImageId={data.cloudinaryImageId}
   cuisines={data.cuisines}
   avgRating={data.avgRating} 
/>;

If we had not destructured and collected the props inside the arrow function parameters itself, then we would have had to do either this:

...

const RestaurantCard = (props) => {

    const { name, cloudinaryImageId, cuisines, avgRating } = props;  

    return (...);

};

...

Or this:

...

const RestaurantCard = (props) => {

    const name = props.name;
    const cloudinaryImageId = props.cloudinaryImageId;
    const cuisines = props.cuisines;
    const avgRating = props.avgRating;

    return (...);

};

...

Before learning how to loop and thus reuse the card component, so that we can render multiple cards, let's understand some concepts, maybe some of these questions are in your mind!

What are props in React?

Props stands for properties. Props are arguments passed into React components. props are used in React to pass data from one component to another (from a parent component to a child component(s)). They are useful when you want the flow of data in your app to be dynamic.

function App() {
  return (
    <div className="App">
      <Tool name="Ruban Sahoo" tool="Figma"/> // name and tool are props
    </div>
  )
}

What is Reconciliation in React?

Reconciliation is the process through which React updates the Browser DOM and makes React work faster. React uses a diffing algorithm so that component updates are predictable and faster. React would first calculate the difference between the real DOM and the copy of DOM (Virtual DOM) when there's an update of components. React stores a copy of Browser DOM which is called Virtual DOM. When we make changes or add data, React creates a new Virtual DOM and compares it with the previous one. Comparison is done by Diffing Algorithm. React compares the Virtual DOM with the Real DOM. It finds out the changed nodes and updates only the changed nodes in Real DOM leaving the rest of the nodes as it is. This process is called Reconciliation.

What is React Fiber?

React Fiber is a concept of ReactJS that is used to render a system faster, smoother and smarter. The Fiber reconciler, which became the default reconciler for React 16 and above, is a complete rewrite of React’s reconciliation algorithm to solve some long-standing issues in React. Because Fiber is asynchronous, React can:

  • Pause, resume, and restart rendering work on components as new updates come in

  • Reuse previously completed work and even abort it if not needed

  • Split work into chunks and prioritize tasks based on importance

Why do we need keys in React?

A key is a special attribute you need to include when creating lists of elements in React. Keys are used in React to identify which items in the list are changed, updated, or deleted. In other words, we can say that keys are unique identifiers used to give an identity to the elements in the lists. Keys should be given to the elements within the array to give the elements a stable identity.

<li key={0}>1</li>
<li key={1}>2</li>
<li key={2}>3</li>

Can we use an index as a key in React?

Yes, we can use the index as keys, but it is not considered good practice to use them because the order of items may change. This can negatively impact performance and may cause issues with component state. Keys are taken from each object which is being rendered. There might be a possibility that if we modify the incoming data react may render them in unusual order.

I've got some dummy data and kept it inside a new file called data.js for the time being.

Now, we will simply use the map function to iterate through the above data and render each restaurant card on the screen. We will also pass a unique key to the RestaurantCard component each time we render it while iterating through our dataset. The reason for passing a unique key has been mentioned several times now!

...
import { restaurantList, CLOUDINARY_BASE_URL } from "./data";

...

const Body = () => {
  const restaurants = restaurantList
    .filter((restaurant) => restaurant.type === "restaurant")
    .map((restaurant) => restaurant.data);
  return (
    <div className="restaurant-list">
      {restaurants.map((restaurant) => (
        <RestaurantCard key={restaurant.id} {...restaurant} />
      ))}
    </div>
  );
};

...
/* Cards list CSS */
.restaurant-list {
  display: flex;
  flex-wrap: wrap;
}

That covers our basic body component as well! You can try out the footer component yourself, in any case, we'll build the footer component in the next blog.

Let's understand some more important concepts, some of these questions may be asked in your interview.

What is Config-Driven UI?

In our application, if you checkout the dataset that I've linked above, the data for every card has a key type which has a value restaurant. Let's say we had a different type of a card (eg: carousel, advertisement, dish), then we would simply have to pass the type and the data accordingly and the frontend code would be written in such a way that according to the type of the card, the card would be rendered differently. So, for any changes to be made in the UI of the card we simply need a change in data which can be controlled or configured by the backend. In large-scale applications, this is a widely adopted practice called config-driven UI.

Config-driven UI is based on the configurations of the data that the application receives from the backend. It is rather a good practice to use config-driven UIs to make applications dynamic. It is a very common & basic approach to interacting with the user. It provides a generic interface to develop things which help your project scale well. It saves a lot of development time and effort. A typical login form is common in most apps. Most of these forms also get frequent updates as the requirements increase in terms of Form Validations, dropdown options or design changes.

Difference between Virtual DOM and Real DOM?

DOM stands for Document Object Model, which represents your application UI. Whenever any changes are made in the application, the DOM gets updated and the user can visualize the changes. DOM is an interface that allows scripts to update the content, style, and structure of the document.

  • Virtual DOM

    • The Virtual DOM is a lightweight abstraction of the DOM. You can think of it as a copy of the DOM, that can be updated without affecting the actual DOM. It has all the same properties as the real DOM object, but can’t write to the screen like the real DOM.

    • Virtual DOM is just like a blueprint of a machine, can make changes in the blueprint but those changes will not directly apply to the machine.

    • Reconciliation is a process to compare and keep in sync the two files (Real and Virtual DOM). Diffing algorithm is a technique of reconciliation which is used by React.

  • Real DOM

    • The DOM represents the web page often called a document with a logical tree and each branch of the tree ends in a node and each node contains objects. Programmers can modify the content of the document using a scripting language like JavaScript.

    • Changes and updates to the DOM are fast because of its tree-like structure. After changes, the updated element and its children have to be re-rendered to update the application UI. This re-rendering of the UI makes the DOM slow.

    • All the UI components need to be rendered for every DOM update, so the real DOM would render the entire list and not just those items that receive the update.

Real DOMVirtual DOM
DOM manipulation is very expensive.DOM manipulation is very easy.
There is too much memory wastage.No memory wastage.
It updates slow.It updates fast.
It can directly update HTML.It can’t directly update HTML.
Creates a new DOM if the element updates.Update the JSX if the element updates.
It allows us to directly target any specific node (HTML element).It can produce about 200,000 Virtual DOM nodes per second.
It represents the UI of your application.It is only a virtual representation of the DOM.

That's all for now folks. See you in the next blog!