3

I am not very experienced with React but I have a very simple Setup.

export default function App() {
  const [title, setTitle] = useState("still-empty");

  const myFunction = title => {
    setTitle(title);
  };

  return (
    <div className="App">
      <ComponentA myFunction={myFunction} />
      <br />
      <br />
      <ComponentB title={title} />
    </div>
  );
}



const ComponentA = ({ myFunction }) => {
  console.log("Rendering Component A");

  return (
    <div onClick={() => myFunction(Math.random() * 1000)}> Component A </div>
  );
};

export default ComponentA;


const ComponentB = ({ title }) => {
  return <div> Title : {title}</div>;
};

export default ComponentB;

Here is a sandbox to test this: https://codesandbox.io/s/musing-cookies-g7szr

See that if you click on "ComponentA", that exact ComponentA gets rerendered (you can see it in console) although no props are changed on this component. This is a simplified example of my real use case. In my real use case, ComponentA is a map where a lot of stuff (zoom, center) will be reset. I want to prevent these resets and also the 1 second it takes for rerendering. Therefor I present this simplified example.

So how do I pass an information from ComponentA to ComponentB, without rerendering ComponentA itself? Thanks for helping out here.

schingeldi
  • 870
  • 2
  • 14
  • 26
  • You are changing the state of the parent component, which re-renders the parent component and its children, i.e ComponentA and ComponentB. If you will regularly being doing stuff like this and don't want any unnecessary re-renders then you should probably look at something like Redux to allow the child components to access state directly. – Paul Ryan Apr 06 '20 at 21:04
  • Thanks for your answer. Yes, I change the state in the parent. But this state variable is not used by ComponentA. So why does it get rerendered? Is there a way around that? – schingeldi Apr 06 '20 at 21:08
  • It doesn't matter that ComponentA is not using the state variable. When you call setState React will mark your parent company as being dirty and will trigger a re-render of it (and thus its sub components, A & B). Even if the value in the state hasn't changed (i.e if you pass it the same value it already has), calling setState will still trigger a re-render. – Paul Ryan Apr 06 '20 at 21:30

1 Answers1

6

use useCallback in Parent so that the function is not created again and again but only on initial render. use React.memo so that when no props are changed the component wont re-render.

App

export default function App() {
  const [title, setTitle] = useState("still-empty");

  const myFunction = useCallback(title => {
    setTitle(title);
  }, []);

  return (
    <div className="App">
      <ComponentA myFunction={myFunction} />
      <br />
      <br />
      <ComponentB title={title} />
    </div>
  );
}

ComponentA

import React, { memo } from "react";

const ComponentA = ({ myFunction }) => {
  console.log("Rendering Component A");

  return (
    <div onClick={() => myFunction(Math.random() * 1000)}> Component A </div>
  );
};

export default memo(ComponentA);

Working demo is here: https://codesandbox.io/s/affectionate-boyd-v7g2t?file=/src/App.js

gdh
  • 13,114
  • 2
  • 16
  • 28