Showing posts with label React. Show all posts
Showing posts with label React. Show all posts

Tuesday, 5 August 2025

React useCallback Hook



We'll use useCallback to :

  • Passing a function as prop to React.memo child
  • Prevents unnecessary re-renders
  • Setting up event handlers inside components
  • Prevents recreation of handler functions
  • Functions inside useEffect/useMemo that need stable reference
  • Avoids infinite loops or unnecessary logic execution
Example : 

import React, { useCallback, useState } from 'react';
import './App.css';
import Dashboard from './component/Dashboard';

const Child = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Click Me</button>;
});

function App() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log('Clicked');
  }, []);

  return (
    <div className="App">
      <Dashboard />
      <h2>React useCallback Example</h2>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child onClick={handleClick} />
    </div>
  );
}

export default App;

React useRef Hook


We'll use useRef to :

  • Automatically focus the input on mount.
  • Allow the user to click a "Focus Input" button to manually refocus.
  • Autofocuses an input on mount
  • Tracks the previous input value
  • Shows how many times the input changed without causing re-renders
Example : 

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

const TodoAppUseRef = () => {
  const inputRef = useRef(null); // Ref for input focus
  const prevInputRef = useRef(''); // Ref for previous input value
  const [tasks, setTasks] = useState([]);
  const [inputValue, setInputValue] = useState('');

  // Auto-focus input on mount
  useEffect(() => {
    inputRef.current?.focus();
  }, []);

  // Update previous input value after each change
  useEffect(() => {
    prevInputRef.current = inputValue;
  }, [inputValue]);

  const handleAddTask = () => {
    if (inputValue.trim()) {
      setTasks([...tasks, inputValue.trim()]);
      setInputValue('');
      inputRef.current?.focus(); // Refocus after adding
    }
  };

  return (
    <div style={{ padding: '2rem', fontFamily: 'Arial', maxWidth: 500 }}>
      <h2>📝 To-Do List</h2>

      {/* Input with ref and value tracking */}
      <input
        ref={inputRef}
        type="text"
        value={inputValue}
        placeholder="Enter a task..."
        onChange={(e) => setInputValue(e.target.value)}
        style={{
          padding: '0.5rem',
          width: '100%',
          marginBottom: '0.5rem',
          fontSize: '1rem',
        }}
      />

      {/* Previous value display */}
      <p style={{ fontSize: '0.9rem', color: 'gray' }}>
        🔙 Previous Input: <strong>{prevInputRef.current}</strong>
      </p>

      {/* Action buttons */}
      <div style={{ display: 'flex', gap: '1rem', marginBottom: '1rem' }}>
        <button onClick={handleAddTask}>Add Task</button>
        <button onClick={() => inputRef.current?.focus()}>🔍 Focus Input</button>
      </div>

      {/* Task list */}
      <ul>
        {tasks.map((task, index) => (
          <li key={index} style={{ padding: '0.3rem 0' }}>
            ✅ {task}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoAppUseRef;

Thursday, 19 December 2024

React useLayoutEffect Hook

useLayoutEffect Work synchronously. and useEffect work with asynchronously.

useEffect it fires synchronously after all DOM loading is done loading.

useLayoutEffect call before DOM update.

App.js file : use hook : useEffect and useLayoutEffect both, but in console you can check first render useLayoutHook. so you can some time calculation or other stuffs before render DOM, you can go with useLayoutEffect hook.

import { createContext, useState, useLayoutEffect, useEffect } from 'react';
import './App.css';

function App() {
  let [name, setName] = useState('Ankit Vyas');

  useEffect(() => {
    console.log('call useEffect.');
    setName('Vyas');
  }, []);

  useLayoutEffect(() => {
    console.log('call useLayoutEffect.');    
    setName('Ankit');
  }, []);

  return (
    <div className="App">  
      My name is : {name}
    </div>
  );
}

export default App;

React portals

React-portals

React write something outside of root element, so we can use React portals.

public/index.html : after root div add one more div with id name is : 'root-test-portal'

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />   
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <div id="root-test-portal"></div> // added this div with id here.
  </body>
</html>

App.js file code

import './App.css';
import TestPage from './Pages/TestPage';
import TestReactPortals from './Pages/TestReactPortals';

function App() {
  return (
    <div className="App">
      <TestPage />
      <TestReactPortals />
    </div>
  );
}

export default App;

/pages/TestReactPortals.js file code

import React, { Component } from "react";
import ReactDom from 'react-dom';

class TestReactPortals extends Component  {
    render() {
        return ReactDom.createPortal(
            <h5>Test React Portals...</h5>,
            document.getElementById('root-test-portal')
        );
    };
}

export default TestReactPortals;

Pages/TestPage.js file code

import React from "react";

const TestPage = () => {
    return (
        <>
            <h2>Test page</h2>
        </>
    );
}
export default TestPage;

Tuesday, 17 December 2024

React Custom Hook

 


Custom hooks must start with keyword is 'use'. Like : useFetchData().

Custom hooks are functions that use one or more times.

Custom hooks create with used also react hook if needed.

app.js file code

import { createContext, useState } from 'react';
import useFetch from './customhooks/useFetch';

function App() {
  const dataFetch = useFetch('Pass API path');

  return (
    <div className="App">
      {dataFetch.map((res) => {
        return (<h4 key={res.id}>
          res.title
        </h4>
        )
      })}
    </div>
  );
}

export default App;

customhooks/useFetch.js

import { useEffect, useState } from "react";

const useFetch = (url) => {

    const [responses, setResponses] = useState([]);

    useEffect(() => {
        fetch(url)
            .then((res) => res.json())
            .then((data) => { setResponses(data) })
    }, []);

    return responses;
}
export default useFetch;

React useEffect Hooks

React : useEffect Hooks : initialise, mounting, updating, unmounting.

React app run and check console also for count.

import { useEffect, useState } from "react";

function App() {

  //useEffect Hooks  : initialise, mounting, updating, unmounting
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("Component mounted or updated. Current count:", count);
   
    return () => {
      console.log("Cleanup before component unmounts or before next effect");
    };
  }, [count]);

 
  const increment = () => {
    setCount(count + 1);
  };
 
  const decrement = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <h1>Counter: {count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );

}

export default App;

Monday, 16 December 2024

React useContext Hook

Pass data parent to child component and child to parent.

Provide using pass value. parent to child component.

Without manually pass data.

Run this code and see the output. using Provider in app.js file pass day Tuesday. and in child component ChildUseContext button onClick pass Day data to parent component.

Example : 1 

...react-practical\src\useContext\UserContext.js

// UserContext.js
import { createContext, useContext } from 'react';

const UserContext = createContext();

export const UserProvider = ({ children }) => {
    const user = {
        name: 'Ankit Vyas',
        role: 'Admin',
    };

    return (
        <UserContext.Provider value={user}>
            {children}
        </UserContext.Provider>
    );
};

// Custom hook for cleaner access
export const useUser = () => useContext(UserContext);

...\react-practical\src\App.js

import Dashboard from './component/Dashboard';
import { UserProvider } from './useContext/UserContext';

function App() {
  return (
    <div className="App">
      <UserProvider>
        <Dashboard />
      </UserProvider>
    </div>
  );
}

export default App;

...\react-practical\src\component\Dashboard.jsx

// Dashboard.jsx
import { useUser } from "../useContext/UserContext";
const Dashboard = () => {
  const user = useUser();
  return (
    <div>
      <h2>Dashboard</h2>
      Name : {user.name}
    </div>
  );
};

export default Dashboard;

Example : 2

...\react-practical\src\useContext\ThemeContext.jsx

// ThemeContext.jsx
import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext();

const themes = {
  light: {
    background: '#ffffff',
    color: '#000000',
    label: 'Light',
  },
  dark: {
    background: '#222222',
    color: '#ffffff',
    label: 'Dark',
  },
};

export const ThemeProvider = ({ children }) => {
  const [themeName, setThemeName] = useState('light');

  const toggleTheme = () => {
    setThemeName((prev) => (prev === 'light' ? 'dark' : 'light'));
  };

  const theme = themes[themeName];

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme, themeName }}>
      {children}
    </ThemeContext.Provider>
  );
};

export const useTheme = () => useContext(ThemeContext);


...\react-practical\src\App.js

import Dashboard from './component/Dashboard';
import { ThemeProvider } from './useContext/ThemeContext';

function App() {
  return (
    <div className="App">
      <ThemeProvider>
        <Dashboard />
      </ThemeProvider>
    </div>
  );
}

export default App;

...\react-practical\src\component\Dashboard.jsx

// Dashboard.jsx
import { useTheme } from "../useContext/ThemeContext";
const Dashboard = () => {
    const { theme, toggleTheme, themeName } = useTheme();
    return (
        <div style={{ background: theme.background, color: theme.color, height: '100vh', padding: '2rem' }}>
            <h2>Dashboard : {themeName}</h2>
            <p>Current Theme: <strong>{theme.label}</strong></p>
            <button onClick={toggleTheme}>
                Toggle to {themeName === 'light' ? 'Dark' : 'Light'} Mode
            </button>
        </div>
    );
};

export default Dashboard;

React useMemo Hook

This hook use with functional component.

Also called Higher order component.

Improve App Performance.

Store Memoized Value.  

When to Use useMemo : 

  • Expensive calculations
  • Filtering/sorting/transforming large datasets
  • Preventing re-renders by reference equality checks

Run this below code and see the difference in console. if we click on count button then show incrementData count in console.

App.js file code

import { createContext, useState } from 'react';
import MemoHook from './Pages/MemoHook';

function App() {
 
  return (
    <div className="App">
      <MemoHook />
    </div>
  );
}
export default App;

Pages/MemoHook.js file code

import React, { useMemo, useState } from "react";

function MemoHook() {
    let [count, setCount] = useState(2);
    let [item, setItem] = useState(22);
   
    console.log("MemoHook count: ", count);
    console.log("MemoHook item: ", item);  

    let incrementData = useMemo(() => {
        console.log('incrementData--->', count, item);        
    }, [count]);
   
    return(        
        <>
            <h3>MemoHook Example : Count {count} : Item {item}</h3>
            {incrementData}
            <button onClick={() => { setCount(count+1); }}>Click Count</button>
            <button onClick={() => { setItem(item+1); }}>Click Item</button>
        </>
    );
}
export default React.memo(MemoHook);

React Pure Components

Restrict the re-rendering when the state and props are value same.

Extend a class with Pure Component.

Run this below code and see the difference in console.

App.js file code

import { createContext, useState } from 'react';
import './App.css';
import PureComponentExample from './Pages/PureComponent';
import NormalComponentExample from './Pages/NormalComponent';

function App() {
  return (
    <div className="App">
        <NormalComponentExample />
        <PureComponentExample />
    </div>
  );
}

export default App;

Pages/PureComponent.js file code

import React, { PureComponent } from 'react';
class PureComponentExample extends PureComponent {
    constructor() {
        super();
        this.state = {
            count: 5
        }
    }

    render() {
        console.log("PureComponent : ", this.state);
        return (
            <>
                <h3>PureComponent Example : {this.state.count}</h3>
                <button onClick={() => { this.setState({ count: 10 }) }}>Click</button>
            </>
        );
    }
}
export default PureComponentExample;

Pages/NormalComponent.js file code

import React, { Component } from 'react';
class NormalComponentExample extends Component {
    constructor() {
        super();
        this.state = {
            count: 5
        }
    }

    render() {
        console.log("NormalComponent : ", this.state);
        return (
            <>
                <h3>NormalComponent Example : {this.state.count}</h3>
                <button onClick={() => { this.setState({ count: 10 }) }}>Click</button>
            </>
        );
    }
}
export default NormalComponentExample;