useRef and useContext Hooks

·

4 min read

liveLink for an example of both hooks

useRef Hook:

useRef hook returns an object with a current property.

  • This object with current property is useful for perform operations that are not possible with react state like focusing on an element or getting height of a DOM element.

  • This object can also be used to store previous value of a variable which ref not used may be lost due to rerendering of react component.

Consider the code below. everytime the user will click on the button the input element will be focused.

import React,{forwardRef, useRef,useState} from 'react'


const Ref = () => {

    // creating ref;
    let inputRef = useRef();
    let[input,setInput] = useState("");

    function Handler(){
//when the button is clicked the input element 
//will be focused because the inputRef.current 

// has the reference of input element just as we use //document.getElementsByTagName('input') in plain js

        inputRef.current.focus();  
    }


  return (
    <div>
        {/* ref assigns the reference of the input element to the inputRef.current  */}

      <input ref={inputRef} value={input} onChange={(e)=>{inputHandler(e)}}/>

        <button  onClick={Handler}>
            Click me to focus input
        </button>
    </div>
  )
}

export default Ref

useRef can also be used to store the previous value of a variable i.e before the rerendering of the component.

// Coded example

import React,{forwardRef, useRef,useState} from 'react'
import ForwardRef from './ForwardRef';

const Ref = () => {

    //creating refs
    let inputRef = useRef();
    let preRef = useRef();

    let[input,setInput] = useState("");

    function inputHandler(e){
        //assigning the value of input to ref
        preRef.current= input;
        setInput(e.target.value)
    }
    // IT WILL HOLD THE VALUE OF INPUT EVEN IF THE COMPONENT RERENDERS 
//here if a javascript variable is used instead of ref //the we will get undefined on every rerender of the component
    console.log(preRef.current)


  return (
    <div>
        <h1 className='text-4xl'> Explanation of Ref</h1>
        <div>

    <input ref={inputRef} value={input} onChange={(e)=>        {inputHandler(e)}}/>

      <span>i am holding the value of previous entered input {preRef.current}</span>

    </div>




    </div>
  )
}

export default Ref

useContext Hook:

Prop drilling is a common issue that occurs in a react js application which be resolved either by using redux or by using useContext Hook.

Prop drilling is when you are required to pass props into a component that is deeply nested.

  • createContext() is used to create a context.

  • Then this context.Provider component can be used as a parent component and all the components that you want to pass the prop to are nested inside this component.

  • context.Provider has a value attribute and the data passed inside this attribute is accessible to all the components no matter how deeply the are nested inside this parent component.

  • The data inside this value attribute is accessed by using useContext(Context) hook.

Consider This coded example to understand useContext.

import React,{createContext,useContext,useState} from 'react';
//creating context named themeContext
const themeContext = createContext();

//useContext will return the data  of the 
//value attribute of themeContext
export function useTheme(){
    return useContext(themeContext);
}

const ThemeContext = ({children}) => {
    let [data,setData] = useState(false);

    function dataFetcher(input){
        setData(input)
    }
  return (
// here we passed an object to the value attribute this //object is now accessiable to all the childrens and 
//can be accessed using useTheme() defined above 
       <themeContext.Provider value={{name:"ali",dataFetcher}}>
       <div className={`${data? 'bg-black text-white':''}`}>
                {children}
            </div>
        </themeContext.Provider>
  )
}

export default ThemeContext
import React from 'react';
import Component1 from './Component1';
import ThemeContext from './contexts/ThemeContext';




const App = () => {


  return (
// This will pass component1 inside ThemeContext component
// making the themeContext.Provider the parent of //component1 hence all the data in value property 
//will be now accessiable to Component1

        <ThemeContext>
            <Component1/>
        </ThemeContext>



  )
}

export default App
import React from 'react';
import Component2 from './Component2';
import { useTheme } from './contexts/ThemeContext';


function Component1() {
    // useTheme will return the data of value property //and using Object desctruction we can extract name from it.
    let {name} = useTheme();

  return (
    <div className='my-2'>
        <h1>i am component 1 i accessed the value = 
            <div className='text-cyan-500'>
                {name} 
            </div>

        from context Provider</h1>


        <Component2/>
    </div>
  )
}

export default Component1
import React,{useState,useEffect} from 'react'
import { useTheme } from './contexts/ThemeContext';
// Remember Component 2 is nested inside Component1 but
 //it still has the access to the value of themeContext.Provider
const Component2 = () => {
    let [bool,setBool] = useState(true);
// useTheme will extract the data inside valueProperty
    let {dataFetcher,name} = useTheme();

    useEffect(()=>{
// directly passing data from Component 2 to 
//the top most component.
        dataFetcher(bool);
    },[bool])



  return (
    <div  className='bg-blue-500 p-2'>
        <h1>i am component 2 {name}</h1>
        <button onClick={()=>{setBool(!bool)}}>
            Click me to change the colors of parent component
        </button>
    </div>
  )
}

export default Component2