skip to Main Content

I am working on a project, where Parent has two Children – A & B.

childA has a list of buttons, and when the user clicks on one of them, I want to capture the ID of the button. HOWEVER, I don’t want childA to be rerendered.

What I want is for childB to receive the ID of the button, and render itself.

I believe using state is why every time a button is clicked, it will rerender ChildA. What’s the right way of achieving the desire behavior here?

(for context, I have simplified things to make the problem clear, in reality childA is a map, and childB is a diagram.)

export function Parent() {
  [buttonId, setButtonId] = useState(null);
  return (
    <>
      <ChildA buttonId={buttonId} onClick={(id) => setButtonId(id)} />
      <ChildA inputId={buttonId} />
    </>
  );
}
export function ChildA({ buttonId, onClick }) {
  return (
    <>
      <Button key='1' onClick={() => onClick(1)}>
      <Button key='2' onClick={() => onClick(2)}>
      <Button key='3' onClick={() => onClick(3)}>
      <Button key='4' onClick={() => onClick(4)}>
      <ElementIDoNotWantRerenderedWhenAButtonIsClicked />
    </>
  );
}
export function ChildB({ inputId }) {
  return (
    <>
      <RenderMeElement inputId={inputId}>
    </>
  );
}

2

Answers


  1. You can use conditional rendering in React JS. This should work for you

    Parent.js

    import {useState} from 'react';
    import ChildA from './ChildA';
    import ChildB from './ChildB';
    
    export function Parent() {
      const [buttonId, setButtonId] = useState(null);
      return (
        <>
          <ChildA buttonId={buttonId} onClick={(id) => setButtonId(id)} />
          <ChildB inputId={buttonId} />
        </>
      );
    }
    

    ChildA.js

      function ChildA(props) {
      const { buttonId, onClick } = props;
      return (
        <>
          <button key='1' onClick={() => onClick(1)}>Button 1</button>
          <button key='2' onClick={() => onClick(2)}>Button 2</button>
          <button key='3' onClick={() => onClick(3)}>Button 3</button>
          <button key='4' onClick={() => onClick(4)}>Button 4</button>
          <button key='5' onClick={() => onClick(null)}>Reset Button</button>
          {!buttonId && <div>Do Not render this when button is pressed</div>}
        </>
      );
    }
    export default ChildA;
    

    ChildB.js

    function ChildB({ inputId }) {
      return (
        <>
          {inputId && <div>RenderMeElement when the inputId {inputId} is not empty</div>}
          
        </>
      );
    }
    export default ChildB;
    

    Notice that I have changed the onClick event from onClick={onClick(1)} to onClick={() => onClick(1)}. This is the official documentation from React explaining it.

    I hope this helps.

    Login or Signup to reply.
  2. You can use React’s React.memo to prevent unnecessary re-renders of ChildA. React.memo is a higher order component, it’s similar to React.PureComponent but for function components instead of classes. If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result.

    Here’s how you can apply it to your ChildA component:

    export const ChildA = React.memo(({ onClick }) => {
      return (
        <>
          <Button key='1' onClick={() => onClick(1)} />
          <Button key='2' onClick={() => onClick(2)} />
          <Button key='3' onClick={() => onClick(3)} />
          <Button key='4' onClick={() => onClick(4)} />
          <ElementIDoNotWantRerenderedWhenAButtonIsClicked />
        </>
      );
    });
    

    https://react.dev/reference/react/memo

    https://react.dev/reference/react/PureComponent

    https://react.dev/learn/render-and-commit

    https://react.dev/learn/state-a-components-memory

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search