Getting Started with React

Introduction

React is a free and open-source frontend javascript library which was created by Facebook and donated as opensource in 2013. React is used for building user interfaces based on UI components. It is maintained by Meta and a community of individual developers and companies.

Reacts are Single Page Applications, wherein DOM/ UI is loaded only once, and next time the page is only updating the data.

React can be used as a base in the development of single-page or mobile applications. However, React is only concerned with state management and rendering that state to the DOM, so creating React applications usually requires the use of additional libraries for routing, as well as certain client-side functionality

React.js does not use a webserver to create virtual DOMs. It builds the virtual DOM and does its diff operations on the client’s browser.

First App

Default App.js

  • Create a New Project
    • npx create-react-app my-app
  • Run the app
    • cd my-app
    • yarn start
  • Your First app is ready

Modify App.js

index.html -> index.js -> App.js ( First page to load is index.html, followed by index.js, and by default configuration invokes App.js)

In React, you can work with JS + HTML together, this is possible using libraries like Babel which converts the JSX syntax to browser compatible JS in the background. For example, Let’s modify the app.js file with the following data

Comparison of JSX to its converted form(from https://babeljs.io/)

Output

First Component

Step1: In the components, folder create the first Welcome.js component file

const Welcome = () => {
    return <h1>this is a first react component</h1>
  }
  export default Welcome

Use this component in App.js

import './App.css'
import Welcome from './components/Welcome'

function App() {
  return <Welcome />
}
export default App

Output

Physical DOM vs Virtual DOM

What is DOM?

When a web page is loaded, the browser creates a Document Object Model of the page. The HTML DOM model is constructed as a tree of Objects:

With the object model, JavaScript gets all the power it needs to create dynamic HTML: i.e JavaScript can change all the HTML elements, CSS styles on the page

Virtual DOM

The virtual DOM (VDOM) is a programming concept where an ideal, or “virtual”, representation of a UI is kept in memory and synced with the “real” DOM by a library such as ReactDOM. This process is called reconciliation.

This approach enables the declarative API of React: You tell React what state you want the UI to be in, and it makes sure the DOM matches that state. This abstracts out the attribute manipulation, event handling, and manual DOM updating that you would otherwise have to use to build your app.

More about Components

Components are Reacts reusable entities.

Component props

Create a Person Component, and use props to take a read-only input and use that in the page.

const Person = (props) => {
    console.log(props)
    return <div>{props.name}</div>
  }
  
  export default Person

In the App.js use pass a value

      <Person name="person1" />

Component State

We will apply useState() to add data to components state and return a reference to variable and function. Let’s see an example of its usage in Counter.js

import { useState } from 'react'

const Counter = () => {
  const [counter, setCounter] = useState(0)

  const onIncrement = () => {
    setCounter(counter + 1)
  }

  return (
    <div>
      <h3>Counter</h3>
      <div>counter: {counter}</div>
      <div style={{ marginTop: '20px' }}>
        <button onClick={onIncrement}>Increment</button>
      </div>
    </div>
  )
}

export default Counter

Output

React Events

OnChange Event

This is known as Event Binding in Angular and helps to get value immediately as when the user changes it, Let us see an example.

import { useState } from 'react'
const Form = () => {
  const [userName, setUserName] = useState('')
  const onChangeInput = (e) => {
    setUserName(e.target.value)
  }
  return (
    <div>
      User name : <input onChange={onChangeInput} />
      <div>{userName}</div>
    </div>
  )
}
export default Form

Output

React + Bootstrap

Add inside index.html the javascript library from https://getbootstrap.com/

    <!-- CSS only -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous"
    />

    <!-- JavaScript Bundle with Popper -->
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
      crossorigin="anonymous"
    ></script>

HTTP Connection + UseEffect Hook + Conditional Rendering

Lets first create component to display a table

const UserTableRow = (props) => {
    const { id, email, first_name, last_name, avatar } = props.user
    return (
      <tr>
        <td>
          <img style={{ width: '30px', height: '30px' }} src={avatar} />
        </td>
        <td>{id}</td>
        <td>{email}</td>
        <td>{first_name}</td>
        <td>{last_name}</td>
      </tr>
    )
  }
  export default UserTableRow

Add HTTP Connection call

import { useEffect, useState } from 'react'
import UserTableRow from '../components/UserTableRow'

const Page1 = () => {
  const url = 'https://reqres.in/api/users'
  const [users, setUsers] = useState()
  useEffect(() => {
    console.log('component got loaded')
    getUsers()
  }, [])

  const getUsers = () => {
    fetch(url)
      .then((result) => result.json())
      .then((result) => {
        setUsers(result)
      })
  }

  return (
    <div>
      <h1 className="page-title">Users List</h1>

      <table className="table table-stripped">
        <thead>
          <tr>
            <th>Avatar</th>
            <th>Id</th>
            <th>Email</th>
            <th>First Name</th>
            <th>Last Name</th>
          </tr>
        </thead>
        <tbody>
          {users &&
            users.data.map((user) => {
              return <UserTableRow user={user} />
            })}
        </tbody>
      </table>
    </div>
  )
}
export default Page1

Signup Component + Axios HTTP

yarn add Axios

Create Signup Code in Signup.js

import { useState } from 'react'

// imoprt axios to make the APIs calls
import axios from 'axios'

const Signup = () => {
  const url = 'http://localhost:4000/user/signup'

  // initially all the user input values will be empty
  const [userName, setUserName] = useState('')
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const signupUser = () => {
    // call the POST api
    axios
      .post(url, {
        name: userName,
        email,
        password,
      })
      .then((response) => {
        // read the response sent by the server
        const result = response.data
        if (result['status'] === 'success') {
          alert('new user signed up')
        } else {
          alert('error while signing up the user')
        }
      })
      .catch((error) => {
        alert(error)
      })
  }

  return (
    <div>
      <h1 className="page-title">Signup</h1>
      <div className="form-group">
        <div className="mb-3">
          <label className="form-label">Full name</label>
          <input
            onChange={(e) => {
              setUserName(e.target.value)
            }}
            type="text"
            className="form-control"
          />
        </div>

        <div className="mb-3">
          <label className="form-label">Email address</label>
          <input
            onChange={(e) => {
              setEmail(e.target.value)
            }}
            type="email"
            className="form-control"
            placeholder="name@example.com"
          />
        </div>

        <div className="mb-3">
          <label className="form-label">Password</label>
          <input
            onChange={(e) => {
              setPassword(e.target.value)
            }}
            type="password"
            className="form-control"
            placeholder="*******"
          />
        </div>

        <div className="mb-3">
          <p>Already have an account? Sign in here.</p>
          <button onClick={signupUser} className="btn btn-success">
            Signup
          </button>
        </div>
      </div>
    </div>
  )
}
export default Signup     

Output

React Toastify

React-Toastify allows you to add notifications to your app with ease.
yarn add react-toastify

Add in app.js the dependency for react-toastify

import { ToastContainer } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
<ToastContainer />

In the SignUp.js, update the toast fields

import { toast } from 'react-toastify'

  const signupUser = () => {
    if (userName.length === 0) {
      toast.warning('please enter user name')
    } else if (email.length === 0) {
      toast.warning('please enter email')
    } else if (password.length === 0) {
      toast.warning('please enter password')
    } else {
      // call the POST api
      axios
        .post(url, {
          name: userName,
          email,
          password,
        })
        .then((response) => {
          // read the response sent by the server
          const result = response.data
          if (result['status'] === 'success') {
            toast.success('new user signed up')
          } else {
            toast.error('error while signing up the user')
          }
        })
        .catch((error) => {
          toast.error(error)
        })
    }
  }

Output

React Router

yarn add react-router-dom

iimport { BrowserRouter, Link, Route, Routes } from 'react-router-dom'

const Component1 = () => {
  return <h1 className="page-title">Component 1</h1>
}

const Component2 = () => {
  return <h1 className="page-title">Component 2</h1>
}

const Component3 = () => {
  return <h1 className="page-title">Component 3</h1>
}

function App() {
  return (
    <div className="container">
      <BrowserRouter>
        <Link to="/c1">Component 1</Link>
        <Link to="/c2">Component 2</Link>
        <Link to="/c3">Component 3</Link>

        <Routes>
          <Route path="/page1" element={<Page1 />} />
          <Route path="/signup" element={<Signup />} />
          <Route path="/signin" element={<Signin />} />
          <Route path="/home" element={<Home />} />

          <Route path="/c1" element={<Component1 />} />
          <Route path="/c2" element={<Component2 />} />
          <Route path="/c3" element={<Component3 />} />
        </Routes>
      </BrowserRouter>

      <ToastContainer />
    </div>
  )
}

Storage

There are scenarios when we need to get data from the browser, i.e it would be difficult to always call the backend to get data from a server or database.

There are two kinds of preferred storage in React i.e Session & Local Storage. Both Session and Local Storage will typically be able to store around 5 MB of data per domain, which is significantly more than cookies(4K).

  • Session Storage
    • SessionStorage gets cleared when the browsing session ends (i.e. when the browser / browser tab is closed), two tabs loaded with the same website will have different sessionStorage data, however sessionStorage data survives page refresh.
  • Local Storage
    •  LocalStorage data, is shared between all tabs and windows from the same origin. LocalStorage data does not expire; it remains after the browser is restarted and even after OS reboot. LocalStorage is available on all browsers, but persistence is not consistently implemented. For ex: Chrome allows users to explicitely clear local storage from settings.

Storing in Session Storage

            // cache properties inside session storage
            // if the keys do not exist, then they will get created with the current values
            // if exist then the values will get overwritten
            sessionStorage['username'] = name
            sessionStorage['email'] = email
            sessionStorage['token'] = token

Retrieving from Session Storage

            sessionStorage['username']

Output with Stored data seen in Session storage.

Redux

Redux is global storage that can be used across components. A Predictable State Container for JS AppsGet Started, Redux is an open-source JavaScript library for managing and centralizing the application state. It is most commonly used with libraries such as React or Angular for building user interfaces. Similar to (and inspired by) Facebook’s Flux architecture, it was created by Dan Abramov and Andrew Clark.

Create a new APP : npx create-react-app redux-demo
Add redux dependencies: yarn add redux-devtools redux react-redux

Step 1: Create Two components First.js, & Second.js to interact between each other

import { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { increment } from '../actions/counterActions'

const First = () => {
  // get the counter from global store
  const counter = useSelector((state) => state.counter)

  // use dispatch to dispatch an action to the reducer
  const dispatch = useDispatch()
  const onIncrement = () => {
    dispatch(increment())
  }
  return (
    <div>
      <h1>First Component</h1>
      <p>Count {counter}</p>

      <button onClick={onIncrement}>Increment</button>
    </div>
  )
}
export default First     
import { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { decrement } from '../actions/counterActions'

const Second = () => {
  // get the counter from global store
  const counter = useSelector((state) => state.counter)

  // use dispatch to dispatch an action to the reducer
  const dispatch = useDispatch()
  const onDecrement = () => {
    dispatch(decrement())
  }
  return (
    <div>
      <h1>Second Component</h1>
      <p>Count {counter}</p>

      <button onClick={onDecrement}>Decrement</button>
    </div>
  )
}
export default Second  

Step 2: Create a countReducer.js inside reducers Folder

const countReducer = (state = 0, action) => {
    switch (action.type) {
      case 'INCREMENT':
        return state + 1
      case 'DECREMENT':
        return state - 1
      default:
        return state
    }
  }
  
  export default countReducer

Step 3: Create a global store store.js

import { combineReducers, createStore } from 'redux'
import counter from './reducers/countReducer'

// create a global store
const store = createStore(combineReducers({ counter }))
export default store

Step 4: Use a Provider in index.js for all components in APP

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'
import { Provider } from 'react-redux'
import store from './store'

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
)
reportWebVitals()

Step 5: Add to App.js

import logo from './logo.svg'
import './App.css'
import First from './components/First'
import Second from './components/Second'

function App() {
  return (
    <div className="App">
      <First />
      <hr />
      <Second />
    </div>
  )
}
export default App

Step 6: Output

Github

https://github.com/jonesjalapatgithub/ReactGettingStarted

https://github.com/jonesjalapatgithub/Redux-demo

error: Content is protected !!
Scroll to Top