Skip to content

Proposal: Don't bail out of reconciliation for pure functions #5219

@gaearon

Description

@gaearon

This might be a terrible idea so I'm just throwing it against the wall here.

React has a core reconciliation principle: if the type has changed, don't bother reconciling.
From my understanding, it has two goals:

  1. It's a good heuristic because it's unlikely that two different components yield similar DOM.
  2. One stateful component instance can't “morph” into another component type.

However, it makes pure function components pretty much the same pain to hot reload as class components currently are. We can't just “swap” <ButtonBeforeEdit> with <ButtonAfterEdit> because React will bail out of reconciliation and destroy any state and DOM under it as a result. This undermines the hot reloading experience in a crucial way, so we have to keep resorting to workarounds like insanely complex proxies.

The interesting thing to note about pure function components is that (2) no longer applies to them. They're stateless and have no instances right? So even if React did not bail out of reconciling different types of stateless component, there would be no weird “morphing” of instances.

It would probably be less efficient in development, but we can live with that. On the other hand, making hot reloading easy with “simple tools” is beneficial because maintaining complex solutions is hard, both for me and for people who depend on my infra and have to wait for my upgrades.

Maybe I'm suggesting something crazy. I'm not sure.
It certainly has important consequences outside of hot reloading or performance changes.

For example, this transition:

const Button = ({ children }) => <div className='button'>{children}</div>;
const Toggle = ({ children }) => <div className='toggle'>{children}</div>;

<Button><StatefulThing /></Button>
<Toggle><StatefulThing /></Toggle>

currently resets the StatefulThing internal state, but with the proposed change, it would not, because merely changing Button to Toggle (two stateless components) is now not, per this proposal, enough to bail out from the reconciliation.

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions