November 29, 2022

React Portals With Examples

Normally in React when a component is rendered, it is mounted into the DOM as a child of the nearest parent node. This works fine for most of the scenarios but sometimes you may want to insert a child into a different location in the DOM. Portals in react provide a way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

Why React portal

So, why is it important to render children into a DOM node outside the parent hierarchy sometimes? There are couple of advantages which are visible when you are using a modal, hovercards or tooltips, basically something which should be displayed as an overlay not as part of the parent component.

  • First advantage is to have a semantically correct HTML. Logically a modal or hovercard should not be part of “root” element, it should be rendered in a separate DOM node.
  • Poroperties for the child node are inherited from the parent component. For example, height, width, overflow: hidden, z-index which may cause modal, tooltip or hover card to be cropped or some part of it hidden.

To avoid the above-mentioned issues, you can use portals in React to render children into a separate DOM node.

React portal Syntax

A portal is created using createPortal() method which is part of react-dom package.

ReactDOM.createPortal(child, container)

Parameters

child- Something that can be rendered such as an element, string, or fragment.

container- DOM node location where child should be injected.

React portal example

As an example, we'll create a Modal dialog box where we need to have a backdrop and the modal box itself. If you click anywhere on the backdrop, modal box should close. There will also be a close button with in the box.

Initially we won't use React portal to render this Modal box which means it will be rendered with in the Parent component.

ModalDialog.js

import './ModalDialog.css'
const ModalDialog = (props) => {
    return (
        <div className="modal-backdrop" onClick={props.handleClose}>
            <div className="modal-content">
                {props.children}
                <button onClick={props.handleClose}>Close</button>
            </div>

        </div>
    );
}

export default ModalDialog;

ModalDialog.css

.modal-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    z-index: 20;
    background-color: rgba(0, 0, 0, 0.75);
}

.modal-content {
    top: 12vh;
    left: 5%;
    width: 50%;
    height: 40%;
    background-color: white;
    padding: 1rem;
    border-radius: 10px;
    z-index: 30;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem; 
}

App.js

Here we have state management for modal (open or closed) using useState hook. There is also a button to open Modal box, clicking this button sets the isModalOpen to true which results in modal box being displayed.

Closing the modal triggers the closeHandler() function which is kind of child to parent component communication by lifting the state up.

import ModalDialog from "./Components/UI/ModalDialog";
function App() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const closeHandler = () => {
    setIsModalOpen(false);
  }
  return (
    <div>
      <button onClick={() => setIsModalOpen(true)}>
          Click to Open Modal
      </button>
      {isModalOpen && <ModalDialog handleClose={closeHandler}> 
        This is Modal Content
      </ModalDialog>}
    </div>
  );
};
React Portals

As you can see Modal is rendered as a Child component of App component wrapped with in root element.

Let's make changes to render Modal outside the DOM hierarchy of the parent component.

In public\index.html add another <div> element. This <div> element is the container for injecting the Modal.

<div id="modalOverlay"></div>
<div id="root"></div>

In the ModalDialog.js wrap the code with in createPortal() method.

import reactDom from 'react-dom';
import './ModalDialog.css'
const Modal = (props) => {
    return (
        <div className="modal-backdrop" onClick={props.handleClose}>
            <div className="modal-content">
                {props.children}
                <button onClick={props.handleClose}>Close</button>
            </div>

        </div>
    );
}
const portalElement = document.getElementById('modalOverlay');
const ModalDialog = (props) => {
    return reactDom.createPortal(<Modal handleClose={props.handleClose}>{props.children}</Modal>, portalElement);

}

export default ModalDialog;

Points to note here-

  1. First you need to import from react-dom. You can also import createPortal directly
    import { createPortal } from 'react-dom';
    	
  2. createPortal() method takes two arguments, first is the child that has to be rendered. To make it more readable what constitutes a child has been assigned to a constant Modal.
  3. Second argument to the createPortal() method is a container. We already added one <div> element in the index.html with id as “modalOverlay”. That element is assigned to another constant portalElement.
  4. Use of portal only changes the DOM tree structure not the parent child component relationship. <ModalDialog> is still used in App.js to render the child component. props are also used to have parent-child communication the same way as before.
React Portals Example

Now Modal component is rendered into a separate DOM node outside the DOM hierarchy of the parent component.

That's all for the topic React Portals With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

November 28, 2022

JDBC Driver Types

JDBC API in Java programming language provides a standard, universal way to connect to databases. It is the responsibility of different DB vendors to provide the implementation of the interfaces in JDBC API and that implementation by DB vendors is provided as JDBC drivers.

Types of JDBC drivers

Based on these different implementations JDBC drivers are categorized into four types.

  • Type 1 driver: JDBC-ODBC bridge JDBC driver
  • Type 2 driver: Written partly in Java and partly in native code
  • Type 3 driver: Pure Java client and middleware server translating client request to data source.
  • Type 4 driver: Written completely in Java.

Type 1 JDBC Driver

Type 1 JDBC driver implements the JDBC API as a mapping to another data access API, such as ODBC (Open Database Connectivity).

The JDBC-ODBC Bridge driver is an example of type 1 JDBC driver that maps JDBC API requests to ODBC requests.

Disadvantages
  1. Type 1 driver is an old driver that is not supported any more by Oracle.
  2. These drivers are not fully written in Java and depends on native library so Type 1 drivers are not portable.
  3. Each JDBC call is mapped to ODBC request and then to DB making it very slow.
Type 1 JDBC driver

Type 2 JDBC Driver

Type 2 JDBC drivers are written partly in the Java programming language and partly in native code. These drivers use native client side libraries specific to the data source to which they connect to.

Oracle's OCI (Oracle Call Interface) client-side driver is an example of a Type 2 driver.

Disadvantages
  1. Since native libraries are required so there is platform dependency.
  2. JDBC calls are translated to native calls using native libraries making it a slow driver though not as slow as Type 1 driver.
  3. Native API must be installed on the client machines.
Type 2 JDBC Driver

Type 3 JDBC Driver

In Type 3 JDBC driver client is written in Java which connects to a middleware server using a database independent protocol. JDBC calls from the client are translated by middleware server to the vendor specific DB calls and then forwarded to the data source.

Disadvantages
  1. Requires a middleware server.
  2. Since there are two stages; JDBC call to midleware server then vendor specific translation and communication to the DB so the JDBC call processing takes more time.
Type 3 JDBC Driver

Type 4 JDBC Driver

Type 4 JDBC drivers are written completely in Java and don't require any native code libraries or middleware server to sit in the middle. Type 4 drivers implement the network protocol for a specific data source and connect directly to data source.

Type 4 JDBC drivers are also known as thin drivers

Disadvantages
  1. Since driver itself implements the vendor specific network protocol so Type 4 drivers are DB specific and generally supplied by the DB vendors.
Type 4 JDBC Driver

That's all for the topic JDBC Driver Types. If something is missing or you have something to share about the topic please write a comment.


You may also like

November 25, 2022

React useContext Hook With Examples

In React application, props is one way to pass data from parent to child component. But it may become an overhead to maintain props in each component if you have a big hierarchy of nested components. React Context API provides another way to maintain global state. Once a context is created with some value in a component, that context will be available to all the nested child components without using "props". The useContext hook in React is used to read the context value in a component where it is needed.

Why useContext hook in React

First let's try to understand what exactly is the problem with props where useContext hook provides a better alternative than "props-drilling".

As an example, we have 3 components ComponentA, ComponentB and ComponentC and we have to pass data from parent component (ComponentA) to child component.

ComponentA.js

From ComponentA, value for theme is passed to the child component, ComponentB.

import ComponentB from "./ComponentB";
const ComponentA = () => {
    return(
        <ComponentB theme="dark"></ComponentB>
    );
}    
export default ComponentA;

ComponentB.js

The same theme value has to be passed to the ComponentC so you'll again use props to pass it further down.

import ComponentC from "./ComponentC";
const ComponentB = (props) => {
    return(
     <ComponentC theme={props.theme}></ComponentC>
    );
}    
export default ComponentB;

ComponentC.js

const ComponentC = (props) => {
    return (
        <p>Current theme is- {props.theme}</p>
    );
}    
export default ComponentC;

Though a simple example with not much nesting but the problem here, as you can notice, is that ComponentB has to do the task of passing the props further down to make it available to ComponentC. You don't have any mechanism to pass that data directly from ComponentA to ComponentC so that all the components in the hierarchy don't have to manage props.

Context provides you with that mechanism to provide data to the nested components without the overhead of managing props.

How to work with useContext

In order to understand how useContext works you'll have to understand the working of React Context API which has three main steps.

  1. Create context using React.createContext.
  2. Enclose the component with <CreatedContext.Provider>. Using Provider lets you provide a context value.
    <CreatedContext.Provider value="ctxValue">
        <SomeComponent />
    </CreatedContext.Provider>
    

    React Context guarantees that this SomeComponent component and any components inside it, no matter how deep, will be able to access the passed context values.

    If the passed context values change, React will re-render the components reading the context as well.

  3. Read the context value in the Component where you need it using useContext() hook.

useContext hook syntax

const value = useContext(SomeContext)

parameters

SomeContext: The argument passed to the useContext() is the context that you've previously created with createContext.

useContext returns the context value for the calling component.

useContext React example

If we take the same example of 3 components ComponentA, ComponentB and ComponentC where we have to pass some data from parent component (ComponentA) to child component. This time we'll use Context to pass data.

1. Creating Context

First step is to create Context. Since many components in different files will need access to the same context so it's common to declare contexts in a separate file.

Contexts.js

import { createContext } from 'react';
export const ThemeContext = createContext('light');

You can pass default value while creating context. If matching context provider is not present default value acts as a fallback value. If you don't have any meaningful default value, pass null while creating context.

Note that Context value can be anything an object, function handle, string. Here we are using a string value.

2. Providing context

createContext() returns a context object which in itself doesn’t hold any information. Typically, you will enclose your higher component with the <Context.Provider> specifying the context value.

App.js

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ComponentA></ComponentA>
    </ThemeContext.Provider>
  );
};

export default App;

Now the ComponentA component and any components inside it, no matter how deep, will be able to access the passed context values.

ComponentA.js

import ComponentB from "./ComponentB";

const ComponentA = () => {
    return(
        <ComponentB />
    );
}    
export default ComponentA;

As you can see now there is no need to pass theme value using props.

ComponentB.js

import ComponentC from "./ComponentC";
const ComponentB = () => {
    return(
     <ComponentC />
    );
}    
export default ComponentB;

3. Accessing Context value.

Read the context value in the Component where you need it using useContext() hook which lets you read and subscribe to context from your component.

ComponentC.js

import { useContext } from "react";
import { ThemeContext } from "./Contexts";

const ComponentC = () => {
    const themeCtx = useContext(ThemeContext);
    return (
        <p>Current theme is- {themeCtx}</p>
    );
}    
export default ComponentC;

Passing dynamic data via context

In the above example value passed with Context provider is hardcoded but most of the times you will want it to be a dynamic value. To update context, you need to combine it with useState hook. Declare a state variable in the parent component and pass the current state down as the context value to the provider.

Here is the changed App.js where we have a checkbox to select theme, which is managed in a state variable named isDarkMode. In the context provider value is now changed dynamically using the current state.

import './App.css';
import { useState } from 'react';
import { ThemeContext } from './components/Examples/Contexts';
import ComponentA from './components/Examples/ComponentA';

function App() {
  const [isDarkMode, setIsDarkMode] = useState(0);
 
  return (

    <div>
      <input
        type="checkbox"
        checked={isDarkMode}
        onChange={e => setIsDarkMode(e.target.checked)}
      />
      Dark mode

      <hr />
      <ThemeContext.Provider value={isDarkMode? 'dark-mode' : 'light-mode'}>
        <ComponentA></ComponentA>
      </ThemeContext.Provider>
    </div>  
  );
}
export default App;
useContext hook React
useContext hook example

For example where context value is an object, check this post- React Context API With Examples

That's all for the topic React useContext Hook With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

November 23, 2022

React useRef Hook With Examples

In this tutorial you'll see what is useRef() hook in React, how to use it and where to use it.

useRef() hook in React

useRef is a built-in hook in React which is used to reference a value that can be persisted across re-renders.

Syntax of useRef hook is as given below-

const ref = useRef(initialValue)

useRef returns an object with a single property named 'current'. Initially this property current is set to the initialValue you have passed. It can be a value of any type.

You can later set the value of ref.current property to something else.

Important points about useRef hook

  1. The returned reference object will persist for the full lifetime of the component, which means it won't change between component re-renderings.
  2. You can change its current property to store information and read it later. This is possible because reference object is persisted across all renders.
  3. Changing the current property doesn’t trigger a component re-rendering. That’s how useRef differs from useState hook where state change triggers a re-render.

useRef React Examples

Two use cases where useRef can be used are.

  1. Directly accessing DOM nodes.
  2. Persisting a value across renders.

Directly accessing DOM nodes

You can use useRef hook in combination with ref attribute to get access to the DOM nodes. Once you have access to the DOM node you can perform operations like focusing on an element, getting value of an element.

In the example we'll have a form with two input elements for entering user name and city. We'll use refs-

  1. To focus on the name input field.
  2. To access values of the input elements so that we can do some basic validation like elements have some value or not.

Steps to access DOM elements using refs are as follows

  1. Define a ref object using useRef() hook. For example const cityRef = useRef();
  2. Pass the ref object to the ref attribute of the element <input type="text" id="city" ref={cityRef} />
  3. Once the association is done cityRef.current stores that DOM node. So, you have access to <input>’s DOM node.

UserDetails.js (Uses react-bootstrap for styling)

import { useEffect, useRef, useState } from "react";
import { Alert, Card } from "react-bootstrap";

const UserDetails = () => {
    const nameRef = useRef();
    const cityRef = useRef();
    const [error, setError] = useState({show:false,
                                        title:'',
                                    errorMsg:''});
    useEffect(() => {
        nameRef.current.focus();
    }, []);
    const submitHandler = (event) => {
        event.preventDefault();
        const enteredName = nameRef.current.value;
        const enteredCity = cityRef.current.value;

        if(enteredName.trim() === '' || enteredCity.trim() === ''){
            setError({show:true,
                title:'Invalid Input',
                errorMsg:'Please enter a valid value for both name and city'});
            return;
        }
        console.log('Name ' + nameRef.current.value);
        console.log('City ' + cityRef.current.value);
        nameRef.current.value = '';
        cityRef.current.value = '';
    }
    const handleClose = () => {
        setError({show:false,
            title:'',
        errorMsg:''});
    }
    return (
        <Card className="mt-3 mx-auto" style={{ width: '25rem' }}>
            <form onSubmit={submitHandler}>
                    <Alert show={error.show} variant="danger" onClose={handleClose} dismissible>
                    <Alert.Heading>{error.title}</Alert.Heading>
                    <p>{error.errorMsg}</p>
                </Alert>
                <label htmlFor="name">User Name</label>
                <input type="text" id="name" 
                    placeholder="Enter user name" ref={nameRef} />
                <br/>
                <label htmlFor="city">City</label>
                <input type="text" id="city" 
                    placeholder="Enter city" ref={cityRef} />
                    <br/><br/>
                <div>
                    <button onClick={submitHandler}>Submit</button>
                </div>
            </form>
        </Card>
    )
}

export default UserDetails;
  1. In the code, element focusing is done inside the useEffect() hook. Since nameRef.current stores reference to the name input node, when the component mounts, you can call focus() on the html element using this ref.
  2. nameRef.current and cityRef.current store references to the name and city input elements respectively. By accessing value attribute of these elements, you can get values of these inputs and do the required validation. This logic is written in submitHandler() function.
  3. useState() hook is used to set the error state. An error object is used which has these properties show, title, errorMsg. Error message is displayed if show property is set to true.

Persisting a value across renders

useRef can store a mutable value across different renders. How that can be useful? Let's try to understand with an example.

Suppose you have written a component Timer to show current time and you are using setInterval() JavaScript function to call the given function after given time interval (1 second in our case). There is also a button to stop refreshing time. Button click triggers an event handler where we need to call clearInterval() function.

There is one problem though, how to get access to myInterval in stopTimer function as myInterval is not in scope there.

import { useEffect, useRef, useState } from "react";
const Timer = () => {
    const [time, setTime] = useState(new Date());
    useEffect(() => {
        const myInterval = setInterval(() => {
            setTime(new Date());
        }, 1000);
    });
    const stopTimer = () => {
        //Needs access to id (myInterval) to clear interval
    }
    return (
        <div>
            Time is: {time.toLocaleTimeString()}
            <br />
            <button onClick={stopTimer}>Stop</button>
        </div>
    );
}

export default Timer;

That's where you can use useRef hook to store myInterval id so that it can be accessed anywhere in the component and retains its value during re-renders.

import { useEffect, useRef, useState } from "react";

const Timer = () => {
    const [time, setTime] = useState(new Date());
    const intervalRef = useRef();
    useEffect(() => {
        const myInterval = setInterval(() => {
            setTime(new Date());
        }, 1000);
        intervalRef.current = myInterval;
        return () => clearInterval(intervalRef.current);
    });
    const stopTimer = () => {
        //Needs access to id (myInterval) to clear interval
        clearInterval(intervalRef.current);
    }
    return (
        <div>
            Time is: {time.toLocaleTimeString()}
            <br />
            <button onClick={stopTimer}>Stop</button>
        </div>
    );
}

export default Timer;
In the code useRef returns a reference object intervalRef which is then used to store the myInterval id.
intervalRef.current = myInterval;
When interval has to be cleared same reference object can be accessed.
 
clearInterval(intervalRef.current);

That's all for the topic React useRef Hook With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

November 22, 2022

React useCallback Hook With Examples

As a performance optimization, React lets you cache (memoize) a component, a function or a computed value.

If you want to memoize a component then you can use React.memo.

If you want to memoize a computed value then you can use useMemo() hook.

If you want to cache a function during component re-renders then you can use useCallback() hook in React.

Why useCallback hook

In JavaScript, functions are First-class functions (or first class objects) which means functions in JS are treated like any other variable. For example, a function can be passed as an argument to other functions, can be returned by another function and can be assigned as a value to a variable.

Read more about it here.

Since functions are considered objects so rules of reference equality will apply on functions in JS. Consider the following example where sayHello() function returns another function.

function sayHello() {
  return () => {
    console.log("Hello!");
  };
}
const f1 = sayHello();
const f2 = sayHello();
console.log(f1 === f2); // false
console.log(f1 === f1); // true

f1 and f2 holds two instances of the same function but they are considered separate instances. Comparing them returns false because they have separate references.

What does that mean in terms of React components? Well, when the components are re-rendered the same function in the component is re-created (a separate instance from the previous copy of the same function). For example, a quite common scenario where you call a function as an event handler to add another object to array of objects.

  const [persons, setPerson] = useState([]);
  const addToPerson = (personData) => {
    setPerson(()=>{
      return [...persons, personData];
    });
  };

This function will be considered a different object every time the component, where this function resides, re-renders.

How does useCallback hook work

In React, when a component re-renders, React re-renders all of its children recursively. When you want to optimize rendering performance, you will sometimes need to cache the functions that you pass to child components.

In order to cache a function between re-renders of your component, wrap the function definition into the useCallback Hook.

Syntax of React useCallback hook is as give below-

useCallback(func, dependencies)

Parameters

func: The function that you want to memoize. It can take any arguments and return any values. React will return your function back to you during the initial render and cache it. On subsequent renders, React will return the cached function if the dependencies have not changed since the last render. If the dependencies have changes, it will give you the function that you have passed during the current render, and store it in case it can be reused later.

dependencies: An array of all values referenced inside of the function.

useCallback React example

You don't have to wrap all the function in a component inside useCallback hooks. One use case, where it may be a good step to Cache a function with useCallback, is when you pass a function as a prop to a component wrapped in memo.

In the example there is a component PersonList.js which displays the list of person objects and also provides the functionality to add a new person object.

In the Parent component (App.js) there is a state for theme to toggle between dark and light mode. State for array of person objects is also managed here.

PersonList.js

import React, { useState } from "react";

const PersonList = (props) => {
    console.log('In PersonList Component')
    const [name, setName] = useState('');
    const changeHandler = (event) =>{
        setName(event.target.value);
    }
    const clickHandler = () => {
        const personData = {
            id: Math.round(Math.random() * 10),
            name: name
        }
        props.addPerson(personData);
        setName('');
    }
    return(
        <div>
            <h2>Person List</h2>
            {props.persons.map((person) => {
                return <p key={person.id}>{person.name}</p>
            })}
            Enter Name: <input type="text" name="pname" value={name} onChange={changeHandler}></input>
            <button onClick={clickHandler}>Add Person</button>
        </div>
    );
}

export default React.memo(PersonList);

Note the wrapping of PersonList in memo to avoid its re-rendering for theme change.

App.js

import { useState } from 'react';
import PersonList from './components/MemoDemo/PersonList';
import './components/MemoDemo/theme.css';

function App() {
  const [isDarkMode, setIsDarkMode] = useState(0);
  const [persons, setPerson] = useState([]);
  const addToPerson = (personData) => {
    setPerson(()=>{
      return [...persons, personData];
    });
  };

  return (

    <>
      <input
        type="checkbox"
        checked={isDarkMode}
        onChange={e => setIsDarkMode(e.target.checked)}
      />
      Dark mode

      <hr />
      <div className={isDarkMode ? 'dark-mode' : 'light-mode'}>
        <PersonList persons={persons} addPerson={addToPerson} />
      </div>
    </>  
  );
}

export default App;

Theme.css

.dark-mode {
  background-color: black;
  color: white;
}
.light-mode {
  background-color: white;
  color: black;
}

Since you have wrapped PersonList inside React.memo so you may think that it should not be re-rendered for the theme state change as theme is not one of the prop for PersonList.

<PersonList persons={persons} addPerson={addToPerson} />

But that doesn't happen and PersonList is re-rendered for theme changes too.

React useCallback Hook

That is happening because of the re-creation of the function addToPerson(). As already explained above; function, if recreated again, is considered a different instance. Since it is one of the props addPerson={addToPerson} and function is considered a new instance so new props and old props are not same thus the PersonList component is re-rendered despite using React.memo.

That's where you can use useCallback() to cache the function itself. You just need to wrap the addToPerson function in App.js inside useCallback.

const addToPerson = useCallback((personData) => {
  setPerson(()=>{
    return [...persons, personData];
  });
}, [persons]);

Now change in theme state doesn't render the PersonList component.

useCallback example

That's all for the topic React useCallback Hook With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

React useMemo Hook With Examples

In the post React.memo With Examples we have seen how you can use it to memoize a whole component in order to avoid unnecessary re-renderings and have some performance gain. On the same lines you can use useMemo hook in React to memoize a computed value so that same cached value can be used in subsequent re-renderings. That way you can avoid unnecessary computations during re-renders and have some performance gain.

How does useMemo hook work

useMemo Hook lets you cache the result of a calculation between component re-renders.

Syntax of useMemo hook in React is as given below-

useMemo(calculateValue, dependencies)

Parameters

  • calculateValue: It is the function which calculates the value that you want to memoize. It should be a pure function, should take no arguments, and should return a value of any type.
  • dependencies: The list of all values referenced inside the calculateValue function. These reactive values include props, state, and all the variables and functions declared directly inside your component body.

React will call your function during the initial render and return the result of calling calculateValue.

On subsequent renders, React will return an already stored value from the last render if the dependencies have not changed. For that React will compare the dependencies with the dependencies you passed during the last render.

Otherwise, it will call calculateValue, return its result, and store it in case it can be reused later.

useMemo() React example

In this example we'll have a component Child.js where we have a function computeExpensiveValue that has a for loop which runs 1000000 times to simulate an extensive computation.

We are also managing two states; count (used in computeExpensiveValue function) and isDarkMode (for theme, which is not used in computeExpensiveValue function).

Since any state change triggers re-rendering so computeExpensiveValue function will also run whenever state changes for either count or theme. Since computeExpensiveValue function has a dependency on count so it should run again for count state change but it has no dependency on theme state change still the function with its loop runs for that also when the component re-renders.

App.js

import Child from './components/MemoDemo/Child';

function App() {
  const [isDarkMode, setIsDarkMode] = useState(0);
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1);
  };
  return (

    <>
      Count: {count}
      <button onClick={increment}>+</button>
      <br />

      <input
        type="checkbox"
        checked={isDarkMode}
        onChange={e => setIsDarkMode(e.target.checked)}
      />
      Dark mode

      <hr />
      <Child count={count} theme={isDarkMode? 'dark-mode' : 'light-mode'}/>
  );
}

export default App;

Child.js

import './theme.css';
const Child = (props) => {
    const computeExpensiveValue = () => {
        console.log('In computeExpensiveValue function');
        let num = props.count;
        for(let i = 0; i < 1000000; i++){
            num += 1;
        }
        return num;
    };
    return(
        <div className={props.theme}>
            <h2>Expensive Calculation</h2>
            {computeExpensiveValue()}
        </div>
    );
}

export default Child;

theme.css

.dark-mode {
    background-color: black;
    color: white;
}
.light-mode {
    background-color: white;
    color: black;
}
React useMemo Hook

As you can see log in the function is displayed for both count and theme state changes.

Wrapping the computeExpensiveValue() function with in the useMemo() hook and providing count as dependency ensures that the computed value of the function is memoized. When the count state changes, function will run again because of the dependency but the cached value will be returned when the theme state changes.

import { useMemo } from 'react';
import './theme.css';
const Child = (props) => {
    const computeExpensiveValue = useMemo(() => {
        console.log('In computeExpensiveValue function');
        let num = props.count;
        for(let i = 0; i < 1000000; i++){
            num += 1;
        }
        return num;
    }, [props.count]);
    return(
        <div className={props.theme}>
            <h2>Expensive Calculation</h2>
            {computeExpensiveValue}
        </div>
    );
}

export default Child;

Now change in theme state doesn't result in the computeExpensiveValue() function execution. Note that Child component is still re-rendered only thing that is cached is the value of the function because of the use of useMemo hook.

That's all for the topic React useMemo Hook With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

November 18, 2022

React.memo With Examples

When we create an application, we would definitely want it to be well optimized and performing fast. React.memo is one such performance optimization technique provided in React.


What is React.memo

In React, when a component re-renders, React re-renders all of its children recursively even if child component has no changes. What if you could check if child component has any changes and re-render it only if there are changes otherwise use the cached version of child component when parent component re-renders.

That's what React.memo does, with memo, you can create a component that React will not re-render when its parent re-renders as long as its new props are the same as the old props. Such a component is said to be memoized.

How to use React.memo

Syntax of memo is as given below-

const MemoizedComponent = memo(SomeComponent, arePropsEqual?)

To memoize a component, wrap the component in a call to memo. It returns a memoized version of the wrapped component to speed up the render process.

React.memo only checks for prop changes. By default, it will only shallowly compare complex objects in the props object. Which means it will only check for value equality not for reference equality. Passing one or more references types as a prop will break the memoization and cause the component to re-render.

You can also provide a custom comparison function, which React then uses to compare the old and new props instead of using shallow equality. This function is passed as a second argument to memo. It should return true only if the new props would result in the same output as the old props; otherwise, it should return false.

React.memo example

In the example there is a parent component MovieLikes which shows the likes count and delegates the rendering of the movie information to the Movie Component.

MovieLikes.js

import Movie from "./Movie";

const MovieLikes = (props) => {
    console.log('Rendering MovieLikes Component')
    return(
    <div>
        <Movie title={props.title} genre={props.genre} />
        <span>Likes: {props.likeCount}</span>
    </div>
    );
}
export default MovieLikes;

Movie.js

import React from "react";
const Movie = (props) => {
    console.log('Rendering Movie Component')
    return(
    <div>
        <p>Title: {props.title}</p>
        <p>Genre: {props.genre}</p>
    </div>
    );
}
export default Movie;

App.js

function App() {  
  const [likeCount, setLikeCount] = useState(0);
  function incrementLikeCount() {
    setLikeCount(likeCount + 1);
  }
  return (
    <div>
      <MovieLikes title="The Conjuring" genre="horror" likeCount={likeCount} />
      <button onClick={incrementLikeCount}>Like</button>
    </div>
  );
}
export default App;

Here we have a 'Like' button, clicking it results in state change and as a consequence component re-rendering happens.

memo in React

As you can see log placed in the Movie component is also displayed every time meaning Movie component is also rendered with each state change even though props to Movie component does not change.

Movie component can be wrapped inside a memo to prevent this unwanted re-rendering of the Movie component and saving the time spent in the re-rendering of this component.

Here is the changed Movie component. Note that React.memo is used with the export.

import React from "react";
const Movie = (props) => {
    console.log('Rendering Movie Component')
    return(
    <div>
        <p>Title: {props.title}</p>
        <p>Genre: {props.genre}</p>
    </div>
    );
}
export default React.memo(Movie);

With that change now you can see that the Movie component is not re-render whenever Like button is clicked.

React.memo example

Important points about React.memo

  1. React.memo is a higher order component. A higher-order component is a function that takes a component and returns a new component.
  2. Use React.memo with functional components not with class components.
  3. React.memo only checks for prop changes. If the props passed down to the component doesn't change you will get the memoized component. If the props change then the component is re-rendered.
  4. If your function component wrapped in React.memo has a useState, useReducer or useContext Hook in its implementation (something other than props), it will still re-render when state or context change.
  5. Use memo with components that render quite often.
  6. You will have to ensure that the time spent in re-rendering of the component is more than the time consumed in the comparison of props (old and new props) then only you will have performance gain otherwise memo may increase the total rendering time.

React.memo Vs useMemo()

Since React.memo and useMemo hook both are used for memoization in React so it is important to know what is the difference between them.

React.memo is a higher-order component whereas useMemo is a react hook. React.memo caches the whole component and returns the component during re-renders. useMemo caches the computed value and returns that during re-renders.

That's all for the topic React.memo With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

November 4, 2022

GenericOptionsParser And ToolRunner in Hadoop

When you run MapReduce program from command line you provide the jar name, the class that has the code, input and output paths in HDFS. That’s the bare minimum you have to provide to run a MapReduce job. There may be other configurations that you can set with in your driver class using conf.set() method. But there is a drawback to setting configurations with in the code, any configuration change would require code change, repackaging the jar and then run it. To avoid that you can opt to provide configurations through the command line at the time of execution. For that purpose you can use GenericOptionsParser class in Hadoop.

GenericOptionsParser class in Hadoop

GenericOptionsParser class is a utility class with in the org.apache.hadoop.util package. This class parses the standard command line arguments and sets them on a configuration object which can then be used with in the application.

The conventional way to use GenericOptionsParser class is to implement Tool interface and then use ToolRunner to run your application. ToolRunner internally uses GenericOptionsParser to parse the generic Hadoop command line arguments and then modify the Configuration of the Tool by setting the command line arguments.

Supported generic options

Options that are supported by ToolRunner through GenericOptionsParser are as follows-

  • -conf <configuration file>- Specify an application configuration file. So you can prepare an XML file and set it using -conf option that way you can set many properties at once.
  • -D <property>=<value>- Sets value for given property. Specifying a property with -D option will override any property with the same name in the configuration file or with in the driver code.
  • -fs <> or <hdfs://namenode:port>- This generic option is used to specify default filesystem URL to use. Overrides ‘fs.defaultFS’ property from configurations.
  • -jt <local> or <resourcemanager:port>- Used to set YARN ResourceManager.
  • -files <comma separated list of files>- Specify comma separated files to be copied to the map reduce cluster. Applies only to job. If you want to add a file to distributed cache then rather than hardcoding it with in your driver code by using job.addCacheFile() method you can specify it using -files generic option.
  • -libjars <comma seperated list of jars>- Specify comma separated jar files to include in the classpath. Applies only to job. If you want to add a jar to distributed cache then rather than hardcoding it with in your driver by using job.addFileToClassPath() method you can specify it using -libjars generic option.
  • -archives <comma separated list of archives>- Specify comma separated archives to be unarchived on the compute machines. Applies only to job. If you want to add an archived file (zip, tar and tgz/tar.gz files) then rather than hard coding it with in your driver by using job.addCacheArchive() method you can specify it using -libjars generic option.

Examples using generic options

1- If you want to set a configuration file.

hadoop jar test.jar com.knpcode.MyClass -conf hadoop/conf/my-hadoop-config.xml /inputfile /outputfile

2- If you want to set value for any configuration. As example setting the number of reducers to 10.

hadoop jar test.jar com.knpcode.MyClass -D mapreduce.job.reduces=10 /inputfile /outputfile
Note that mapred.reduce.tasks property is deprecated, mapreduce.job.reduces property should be used instead.

3- Setting files, jars and archived file in distributed cache.

hadoop jar test.jar com.knpcode.MyClass -files /input/test.txt -libjars /lib/test.jar /inputfile /outputfile

That's all for the topic GenericOptionsParser And ToolRunner in Hadoop. If something is missing or you have something to share about the topic please write a comment.


You may also like

React useReducer Hook With Examples

You might have used useState hook in React to manage state in your application and it works fine for most of the cases but there is another hook useReducer in React that can also help with managing the state in your application.

useReducer() hook has two advantages over the useState hook which are-

  1. useReducer separates the state management logic from the rendering logic which should actually be the focus of the component.
  2. useReducer() hook is better placed to manage complex state in your application. So, if your state may change because of several conditions and relies on some complex logic then you can think of using useReducer instead of useState hook.

React useReducer hook Syntax

useReducer accepts three arguments and returns an array with exactly two values. You can use array destructuring to assign these array items to variables.

const [state, dispatchFunction] = useReducer(reducerFunction, initialArg, init)

Parameters

1. reducerFunction: The reducer function that specifies how the state gets updated. It gets the state and action as arguments, and returns the next state. State and action can be of any types. It must be a pure function.

A function is considered pure, if it follows the following rules:

  • The function always returns the same output for the same set of arguments.
  • The function does not produce any side-effects.

2. initialArg: The value from which the initial state is calculated. It can be a value of any type.

3. init: This is an optional parameter. It is an initializer function that specifies how the initial state is calculated. If initializer function is not specified, the initial state is set to initialArg. Otherwise, the initial state is set to the result of calling init(initialArg).

Returns

useReducer returns an array with exactly two values:

1. The current state.

2. The dispatch function that lets you update the state to a different value and trigger a re-render.

How does useReducer hook work

Initially it may be a little confusing to understand how does useReducer() hook work as lot of work is done by React internally so let's try to understand the working.

1. Initial State- initialArg which is the second parameter in the useReducer specifies the initial state. It can be of any type but generally you will use an object. For example, if you have a counter state which can be changed by two actions 'increment' and 'decrement', then initial state of counter may be 0.

const initialState = {
    count:0
};

2. Dispatch function- dispatch function is returned by the useReducer hook itself. You don't write the logic for dispatch function but you call it. While calling the dispatch function you need to pass the action argument.

action argument specifies the action performed by the user. It can be a value of any type. By convention, an action is usually an object with a type property. For example, on click of Increment button you can dispatch an action of type 'Increment'.

<button onClick={() => dispatch({type: 'Increment'})}>Increment</button>
Optionally you can also send other properties with additional information.
function handleInputChange(e) {
  dispatch({
    type: 'change_value',
    nextValue: e.target.value
  });
}

3. Reducer function- The reducer function (first argument in the useReducer) is called automatically when you call dispatch. You will write the logic for reducer function. Reducer function you've provided will be passed two arguments- the current state and the action (action argument you've passed to dispatch).

4. Reducer function returns the new state and the state is updated to this new state triggering a re-rendering.

useReducer hook React examples

As the first example let's take the often-used example of incrementing and decrementing count state and showing the current count using useReducer.

1. useReducer Counter example

import { useReducer } from "react"

const initialState = {
  count:0
};
const reducer = (state, action) =>{
  let countState;
  console.log(action.type)
  switch(action.type){
    case 'Increment':
      countState =  {count: state.count + 1};
      break;
    case 'Decrement':
      countState =  {count: state.count - 1};
      break;
    default:
      throw new Error();
  }
  return countState;
}
const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
  return(
    <div>
      <p>Current Count- {state.count}</p>
      <button onClick={() => dispatch({type: 'Increment'})}>Increment</button>
      <button onClick={() => dispatch({type: 'Decrement'})}>Decerement</button>
    </div>
  )
}

export default Counter;

Some important points about the code-

  1. You will have to import useReducer in order to use it.
  2. Initial state is defined as an object with count property having initial value as 0.
    const initialState = {
        count:0
    };
    
  3. useReducer is called with a reducer function and initial state.
    const [state, dispatch] = useReducer(reducer, initialState);
    
  4. dispatch is called with appropriate actions as click event handling functions.
    <button onClick={() => dispatch({type: 'Increment'})}>Increment</button>
    <button onClick={() => dispatch({type: 'Decrement'})}>Decerement</button>
    
  5. reducer function gets the dispatched action as one of the argument and uses switch statement to determine the action type and change the state accordingly. Note that reducer function is written outside the component function that is possible because reducer function doesn't use any data that is inside the Component. That is also one of the advantages; useReducer separates the state management logic from the rendering logic.

2. useReducer with form example

This is a better example of useReducer where form validation is done using useReducer. To keep this example a bit simple not much styling is done except some inline styling and it uses two separate reducers to manage form data state and form validation state. Focus is more on understanding the working of useReducer hook in React.

In the form there are 3 fields first name, last name and email. Initial state for form field values and validation is defined as given below.

const initialValueState = {
    firstName: "",
    lastName: "",
    email: ""
}
const initialValidityState = {
    firstNameError: false,
    lastNameError: false,
    emailError: false
}

If you want to manage both values and validation states in a single state you can use state object as given below. As mentioned above, in this example we'll use two separate states.

const initialState = {
  firstName: { value: "", touched: false, hasError: true, errorMessage: "" },
  lastName: { value: "", touched: false, hasError: true, errorMessage: "" },
  email: { value: "", touched: false, hasError: true, errorMessage: "" },
  isFormValid: false,
}

Form validation with useReducer

import { useReducer } from "react";
const initialValueState = {
    firstName: "",
    lastName: "",
    email: ""
}
const initialValidityState = {
    firstNameError: false,
    lastNameError: false,
    emailError: false,
    isFormValid: false
}
const formReducer = (state, action) => {
    const {name, value} = action.type
    // Uses Computed property name ES6
    return{
        ...state, [name]: value, 
    }
}
const formValidityReducer = (state, action) => {
    let isValid = false;
    switch(action.type){
        
        case "VALIDATE_FIRST_NAME": 
            isValid = action.data.firstName.trim().length > 0 ? true: false
            // For formvalidity validity has to be checked for all the form fields
            return{
                ...state,
                ...({firstNameError: !isValid, isFormValid: isValid && 
                    (action.data.lastName.trim() !=="") && 
                    (action.data.email.trim().length > 0 && action.data.email.includes("@"))})
            }
        case "VALIDATE_LAST_NAME": 
            isValid = action.data.lastName.trim().length > 0 ? true: false
            return{
                ...state,
                ...({lastNameError: !isValid, isFormValid: isValid && 
                    (action.data.firstName.trim() !=="") && 
                    (action.data.email.trim().length > 0 && action.data.email.includes("@"))})
            }
        case "VALIDATE_EMAIL": 
            isValid = (action.data.email.trim().length > 0 && action.data.email.includes("@") ) ? true: false
            return{
                ...state,
                ...({emailError: !isValid, isFormValid: isValid && 
                    (action.data.firstName.trim() !=="") && 
                    (action.data.lastName.trim() !=="")})
            }
        default:
            return state
    }
}
const ReduceForm = () => {
    const [formValues, setFormValues] = useReducer(formReducer, initialValueState);
    const [formValidity, setFormValidity] = useReducer(formValidityReducer, initialValidityState)
    const onSubmitHandler = (event) => {
        event.preventDefault();
        // just displaying field values
        console.log(formValues)
    }
    return(
    <form onSubmit={onSubmitHandler}>
         <label htmlFor="firstName">First Name</label>
         <input 
                name="firstName" 
                onChange={(e) =>setFormValues({type:e.target})}
                style={{backgroundColor:formValidity.firstNameError ? "#fce4e4" : ""}} 
                onBlur={(e) => setFormValidity({type: "VALIDATE_FIRST_NAME", data: formValues})}
                type="text"/>
        {formValidity.firstNameError && <p style={{display: "inline-block",color: "#cc0033"}}>First name is required</p>}<br />
        <label htmlFor="lastName">Last Name</label>
         <input 
                name="lastName" 
                onChange={(e) =>setFormValues({type:e.target})}
                style={{backgroundColor:formValidity.lastNameError ? "#fce4e4" : ""}} 
                onBlur={(e) => setFormValidity({type: "VALIDATE_LAST_NAME", data: formValues})}
                type="text"/>
        {formValidity.lastNameError && <p style={{display: "inline-block",color: "#cc0033"}}>Last name is required</p>}
        <br />
        <label htmlFor="email">Email</label>
         <input 
                name="email" 
                onChange={(e) =>setFormValues({type:e.target})}
                style={{backgroundColor:formValidity.emailError ? "#fce4e4" : ""}} 
                onBlur={(e) => setFormValidity({type: "VALIDATE_EMAIL", data: formValues})}
                type="text"/>
        {formValidity.emailError && <p style={{display: "inline-block",color: "#cc0033"}}>Valid email is required</p>}
        <br />
        <div>
            <input disabled={!formValidity.isFormValid} type="submit" value="Submit"/>
        </div>
    </form>
    )
}

export default ReduceForm;

Some points about the code-

  1. Two useReducer hooks are created, in one reducer function is named formReducer and dispatch function is named setFormValues. In another reducer function is named formValidityReducer and dispatch function is named setFormValidityData.
  2. In the formfields, onChange event is used to dispatch action for updating field values state and onBlur event is used to dispatch action for updating field validation state.
  3. Submit button is disabled if the form is not valid. For individual fields input box styling changes and a message is displayed in case of error.
useReducer React example

That's all for the topic React useReducer Hook With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

November 3, 2022

What is Hadoop

Apache Hadoop is an open source framework for storing data and processing of data set of big data on a cluster of nodes (commodity hardware) in parallel.

Hadoop framework is designed to scale up from single server to thousand of machines with each machine offering both storage and computation. It is also reliable and fault tolerant, framework itself is designed to detect and handle failures at the application layer, that way Hadoop framework provides a highly-available service using a cluster of nodes.

Modules of Hadoop

Hadoop framework is written in Java and it includes these modules-

  1. Hadoop Common– This module contains libraries and utilities used by other modules.
  2. Hadoop Distributed File System (HDFS)– This is the storage part of the Hadoop framework. It is a distributed file system that works on the concept of breaking the huge file into blocks and storing those blocks in different nodes. That way HDFS provides high-throughput access to application data.
  3. Hadoop Yarn (Yet Another Resource Negotiator)– This module is responsible for scheduling jobs and managing cluster resources. Refer YARN in Hadoop to read more about YARN.
  4. Hadoop MapReduce– This is the implementation of the MapReduce programming model to process the data in parallel.
Modules in Hadoop

Brief history of Hadoop

Hadoop was created by Doug Cutting and it has its origins in Nutch which is an open source web crawler. When Doug Cutting and Mike Cafarella were working on Nutch and trying to scale it they came across two google white papers about GFS (Google’s Distributed File System) and MapReduce. Using the architecture described in those papers Nutch’s developers came up with open source implementation of distributed file system NDFS (Nutch Distributed File System) and MapReduce.

It was realized that NDFS and MapReduce can be created as a separate project and that way Hadoop initially became a sub-project. Yahoo also helped by providing resources and team to develop the framework by improving scalability, performance, and reliability and adding many new features. In 2008 Hadoop became a top-level project in Apache rather than being a sub-project and now it is a widely used framework with its own ecosystem.

How Hadoop works

Here I’ll try to explain how Hadoop works in very simple terms without going into the complexities what all daemons like NameNode or Resource Manager do.

Once you copy a huge file into HDFS, framework splits the file into blocks and distribute those blocks across nodes in a cluster.

Then you write a MapReduce program having some logic to process that data. You package your code as a jar and that packaged code is transferred to DataNodes where data blocks are stored. That way your MapReduce code work on the part of the file (HDFS block that resides on the node where code is running) and processes data in parallel.

Other advantage is that rather than sending data to code (like traditional programming where data is fetched from DB server) you send the code to data. Obviously data is much larger in size so that way Hadoop uses network bandwidth more proficiently.

Here is a high level diagram which tells in a simple way how Hadoop framework works.

How Hadoop works

That's all for the topic What is Hadoop. If something is missing or you have something to share about the topic please write a comment.


You may also like