0

I made a small experiment while learning React https://codepen.io/bullet03/pen/abGoGvL?editors=0010:

  • React 17.0 with Fiber
  • 2 components: Agregator(Parent) and Counter(Child)
  • Counter(Child) uses useState hook to change it's state
  • NB!!! Agregator(Parent) doesn't return JSX component, but calls Counter(Child) function. I know it's not casual way of using React, but this is the essence of the experiment
  • when click the button of Counter(Child) component we expect only Counter(Child) to be rerendered, but somehow Agregator(Parent) rerenders as well according to the console.log

Here comes the question: Why change of Counter(Child) component state causes Agregator(Parent) component rerender?

function Agregator() {
  console.log("render Agregator");
  return Counter();
}

function Counter() {
  const [count, setCount] = React.useState(0);
  const incCount = () => setCount((prev) => prev + 1);

  console.log("render Counter", count);

  return <button onClick={incCount}>{count}</button>;
}

ReactDOM.render(<Agregator />, document.getElementById("root"));

As far as I know, it shouldn't happen, because rerender of the component is caused by several cases:

  • change of state
  • change of props
  • change of context
  • forceUpdate
  • rerender of ancestor component

None of this is applicable to our case

NB!!! No need to rewrite this experiment to correct one, but it would be greate to get the explanation why in my case it works like this, so change of Child component state causes Parent component to rerender.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
bullet03
  • 73
  • 5
  • 1
    So you are (*knowingly?*) using React incorrectly and asking why it doesn't work correctly? As soon as `Agregator` directly invokes `Counter` as a function all knowns about the normal React component lifecycle are thrown out the window. In other words, you've basically left Reactland. – Drew Reese Sep 01 '22 at 06:18

1 Answers1

1

NB!!! Agregator(Parent) doesn't return JSX component, but calls Counter(Child) function. I know it's not casual way of using React, but this is the essence of the experiment

Then there's only one component at all, and no parent/child relationship, which renders (ha!) your experiment invalid.

Consider what would happen if you used your IDE's Inline Function feature on the Counter() invocation (which is essentially what the JS interpreter does, but with call stack and all that):

function Agregator() {
  console.log("render Agregator");
  // inlined...
  const [count, setCount] = React.useState(0);
  const incCount = () => setCount((prev) => prev + 1);

  console.log("render Counter", count);

  return <button onClick={incCount}>{count}</button>;
  // ... end of inline.
}

ReactDOM.render(<Agregator />, document.getElementById("root"));
AKX
  • 152,115
  • 15
  • 115
  • 172