Performance
Profiler
React Developer Tools provides Profiler that helps identify parts of an application that are slow. Open the browser console and open Profiler panel. Initially the Profiler panel is empty and you can start new session by pressing the Record button. Then you use your React app as you normally would. When you are ready, press the Stop button.
The React profiler show commits that are made in your React app. The commit is the moment when React applies changes to the DOM. In the each commit you can see what components were rendered and the time it takes. If you move cursor to a component, you can also see why it was rendered.

Read more about Profiler in https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html.
React also provides Profiler component that can be used programmatically analyze you React app' sperformance (https://react.dev/reference/react/Profiler)
Excessive re-renders
- It is good to understand that when a component re-renders all of its child components also re-renders, and in some cases this might be potential performance issue.
 - Let's see one practical example:
 
function ParentComponent() {
  const [text, setText] = useState("");
  return (
    <div>
      <input value={text} onChange={e => setText(e.target.value)} />
      <ChildComponent />
    </div>
  );
};
ChildComponentlooks the following.
function ChildComponent() {
  console.log('Child is re-rendered');
  return <p>Child</p>;
};
- Now, each time you type something to the 
inputelement,ChildComponentalso re-renders, and we can see 'Child is re-rendered' text in the console. - What if there is some time-consuming operation in the 
ChildComponentlike in the following example code? 
function ChildComponent() {
  let now = performance.now();
  while (performance.now() - now < 1000) {
    // do nothing for 1000ms
  }
  return <p>Child</p>;
}
- Now, whenever you input text into the text field, there's a 200 ms delay, and the user interface is noticeably slow.
 - The 
ChildComponentis re-rendered each time theParentComponentre-renders, even when no data is changing, and a re-render isn't necessary. - The solution to this problem is so called 'Lifting content up'.
 
export default function App() {
  return (
    <ParentComponent>
      <ChildComponent />
    </ParentComponent>
  );
}
function ParentComponent({children}) {
  const [text, setText] = useState("");
  return (
    <div>
      <input value={text} onChange={e => setText(e.target.value)}>
      {children}
    </div>
  );
};
function ChildComponent() {
  let now = performance.now();
  while (performance.now() - now < 200) {
    // do nothing for 200ms
  }
  return <p>Child</p>;
};
- Now, we pass the 
ChildComponentto theParentComponentusingprops. Whentextstate changes, theParentComponentis re-rendered. But thepropsis not changed; therefore,ChildComponentis not re-rendered. 
The syntax:
<ParentComponent>
  <ChildComponent />
</ParentComponent>
Can be also written in the following way:
<ParentComponent children={<ChildComponent />}>