React renders based on state change but not on prop change?

80
August 21, 2021, at 11:00 AM

The reason I'm having this question is that I do not see how React renders based on prop changes.

On each fiber, beginWork renders the fiber, and if there's any state change, it'll mark the change. And if there isn't, it could bailoutOnAlreadyFinishedWork so to clone the fiber. While doing it, it reconcileChildren so that we know what's the next work unit. During the reconcileChildren, seems to me the the pendingProps for each element is used directly.

The question is that I do not see when the props are shallow compared. I only see the code that I expected in React.memo with shallowEqual and then confirmed with the doc, https://reactjs.org/docs/react-api.html#reactmemo.

So where the props are not checked shallowly by default? Does that mean as long as there's a render, it'll carry the props as a new version?

Thanks if someone knows the answer.

Answer 1

Yes you are right. If the parent state is updated whether it is a redux state or hook it will re render it's all components. But there is a case. Suppose you implemented your child in a way that it will only re render if the props are changed. Then even if the parent re render all it's child the child will not re render itself. This process in react is called memoization. But yes if parent state it updated it will re render all it's child

Reference - https://reactjs.org/docs/react-api.html#reactmemo

Answer 2

I actually found the answer in this article, https://medium.com/takeaway-tech/a-deep-dive-into-pure-component-and-react-memo-and-why-do-we-need-them-ae99dce6a33c .

It firmly says

Remember: in React, props is immutable object.

And unless React.memo is used, props are rendered all the time!!!

Under the beginWork, React does compare the props before it goes into a new render. Here's the source code

function beginWork(current, workInProgress, renderLanes) {
  ...
  if (current !== null) {
    var oldProps = current.memoizedProps;
    var newProps = workInProgress.pendingProps;
    if (oldProps !== newProps || hasContextChanged() || ( // Force a re-render if the implementation changed due to hot reload:
     workInProgress.type !== current.type )) {
      // If props or context changed, mark the fiber as having performed work.
      // This may be unset if the props are determined to be equal later (memo).
      didReceiveUpdate = true;

However oldProps !== newProps is not doing a shallow check, instead it's similar to object.is. And for props, {} !== {} unless it's a cloned copy. Therefore seems to me, props isn't implemented as React advertised it :)

Of course, if there's no state change ,it wouldn't even get into a prop change. So maybe as long as we make sure state is compared correctly, it'll translate into correct rendering? I don't know if this is the correct rational here.

READ ALSO
Format XML ordered list with XSLT

Format XML ordered list with XSLT

I have the following XML-Snippet …

58
How should I get all the messages from my database and return it

How should I get all the messages from my database and return it

I'm making a chat app with Java and I'm getting all the messages to a specific chatroomThe issue is I don't know how to put them all in one array or something so it can be returned all at once to the user

70
Is there a way of mirroring an inheritance relationship using spring-boot-starter-data-elasticsearch?

Is there a way of mirroring an inheritance relationship using spring-boot-starter-data-elasticsearch?

I am new to Elasticsearch and spring-boot-starter-data-elasticsearch

104
Laravel livewire - System failed to continue execution after validation (success or not)

Laravel livewire - System failed to continue execution after validation (success or not)

Inside my livewire blade file I have this form, and inside this form there is a button:

90