Home > front end >  How to avoid re-rendering of child components whenever parent's state is updated
How to avoid re-rendering of child components whenever parent's state is updated

Time:10-14

Home.js =======> Parent component

import React, { useState, useReducer, useRef, createContext } from "react";
import { User1, User2, User3 } from "./User";

export const UserContext = createContext(null);
export const TypeContext = createContext(null); 

const Home = () => {
  const [user, setUser] = useState("User");
  const [type, setType] = useState("Free");
  return (
    <>
      <input type="text" onChange={(event) => setUser(event.target.value)} />
      <br />
      <input type="text" onChange={(event) => setType(event.target.value)} />
      <UserContext.Provider value={{ user }}>
        <User1 />
        
      </UserContext.Provider>
      <TypeContext.Provider value={{ type}}>
        <User2 />
      </TypeContext.Provider>
    </>
  );
};

export default Home;

User.js =============> Child Component

import React, { useContext, useMemo } from "react";
import { UserContext, TypeContext } from "./Home";

export const User1 = () => {
  const { user } = useContext(UserContext);
  console.log("user1");
  return <h1>Username is {user}</h1>;
 };

export const User2 = () => {
  const { type } = useContext(TypeContext);
  console.log("user2");
  return <h1>Username is {type}</h1>;
};

export const User3 = React.memo((props) => {
  console.log("user3");
  return <h2>My Props {props.title}</h2>;
});

It re-renders User1 and User2 every time anything changes in user or type as the state of parent update. I want when I change user only User1 should update and when I update type only User2 should update

CodePudding user response:

Here is a working codesandbox that I created to handle your issue.

Explanation

You should memoize the child components if you want to render them only there is a change. Since you are not passing the values as props, you should also useMemo the context provider values:

Home.js

import { useState, createContext, useCallback, useMemo } from "react";
import { User1, User2 } from "./User";

export const UserContext = createContext(null);
export const TypeContext = createContext(null);

export const Home = () => {
  const [user, setUser] = useState("User");
  const [type, setType] = useState("Free");

  const handleUserChange = (event) => setUser(event.target.value);

  const handleTypeChange = (event) => setType(event.target.value);

  const userValue = useMemo(() => ({ user }), [user]);
  const typeValue = useMemo(() => ({ type }), [type]);

  return (
    <>
      <input type="text" onChange={handleUserChange} />
      <br />
      <input type="text" onChange={handleTypeChange} />
      <UserContext.Provider value={userValue}>
        <User1 />
      </UserContext.Provider>
      <TypeContext.Provider value={typeValue}>
        <User2 />
      </TypeContext.Provider>
    </>
  );
};

export default Home;

User.js

import { useContext, memo } from "react";
import { UserContext, TypeContext } from "./Home";

export const User1 = memo(() => {
  const { user } = useContext(UserContext);
  console.log("user1");
  return <h1>Username is {user}</h1>;
});

export const User2 = memo(() => {
  const { type } = useContext(TypeContext);
  console.log("user2");
  return <h1>Username is {type}</h1>;
});

CodePudding user response:

Changes to the context value will rerender all of the consumers, because React simply does an === comparison on the updated values, and you're creating the object inline (so it's different each time). See https://reactjs.org/docs/context.html#caveats

The solution is to memoize the value you pass to the provider, or use something like Redux or Zustand.

CodePudding user response:

you can use shouldComponentUpdate(nextProps, nextState) for this method. Use shouldComponentUpdate() to let React know if a component’s output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior read docs here. As a suggestion try not to use this unless absolutely necessary, this can cause bugs or performance issues but its the only method I know that is there so hpefully it helps

  • Related