gaearon / gaearon/react-hot-loader

Reversed Hot-Replacement

Open
#1,138 2 comments 6 reactions 0 assignees View on GitHub
enhancement
Dominant language
JavaScript
Stars
12.2k
Forks
775
PR merge metrics
No merged PRs in 30d

Description

parent issue: #1121
is an action for: #1024

There are huge problems updating Class-based components. We fight with them for a year, and look like there is only one way to defeat them - surrender.

### How it works currently
- RHL set prototype from a `new` class to an `old` class
- As long as the class constructor could not be "updated" or "redone" we have to "find" updates manually
- RHL creates `new` and `old` classes, looks for differences (not all of them are visible)
- __overrides__ class variables to replicate changes on the real instances (not all changes are replicatable) using `eval` injected by the babel plugin to maintain the "variable scope" (which might be wrong)

In short - it __lands__ some important "changes" from hot-updated code to the existing ones. Maintaining the state just because it is not updated. The result could be far from reality.

- the prototype-based methods are all "new", they are all right
- any other method update is )transported_ from a new (variable) scope to an old one
- some operations, performed in a constructor, could not be redone and skipped

### Proposal
- create a new component from a scratch, as we are doing
- detect any difference between the `old` component and instance, as we are going
- inject all changes we want to __keep__ to the new instance
- replace old instance by a new one on fiber level.
- update refs if they existed (probably could be done on createElement level)

In short - __keeps__ some important changes, like state or lifetime variables. The result is a reality, the same as if you refresh a page.

This is actually a _refresh_, but with a state kept (and we don't need anything else)

The only difference - we should inject a new instance deeply to `react-dom`.

- 👍 react 16 only
- 👍 babel plugin is __not__ required, as long there is no need to inject updated code to existing classes.
- 👍 any third party code, like [`react-redux` should be hot-reloadable](https://github.com/reduxjs/react-redux/pull/1137) without any change from their side.
- 👍 no more type comparison problem

- 👎 react-🔥-dom is required

It might be a blocker. The more we patch sources of react, the deeper we are in trouble. This this proposal is something, that _should be done_, I am not sure that it's something, that _could be done_.

Contributor guide

Open the contributing guide

Research direction

Start by reading parent issue #1121 and action issue #1024, then trace how React 16 and react-dom currently handle hot replacement of class-based component instances. Done would require a concrete, reviewed design for replacing instances at the fiber level while preserving selected state and refs, plus a feasible implementation plan.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react
Domain
frontend, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
18/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.