Skip to content

Conversation

@gaearon
Copy link
Collaborator

@gaearon gaearon commented May 20, 2019

This PR adds a return value to scheduleHotUpdate:

{|
  hostNodesForVisualFeedback: Array<Instance>
|}

This is an array of host nodes which can be used by the hot reloading runtime to show visual feedback related to the edited UI. Here's a gif to give you an idea of a possible way to use this. Note how the updated components are briefly highlighted in the browser right after edit:

Screen Recording 2019-05-20 at 08 25 PM

(Don't pay too much attention to the concrete visual feedback here; this is something we'll play more with. If this contextual feedback ends up being too much, we can always remove it and use a simple indicator, but I want to experiment more with it.)

The implementation goes as follows:

  • We mark "affected fibers" as we traverse the tree to schedule hot updates.
    • We only mark them one level deep. If Parent and Child were edited in the same file, we'll only mark the Parent. This is because in the visual indication we'll likely want to coalesce children with parents anyway.
  • During the hot update, we keep track of unmounted fibers, and their return references.
    • This will let us walk the parent path for disconnected fibers if necessary (see below why).
  • After the hot update batch is flushed, we determine the host nodes:
    • If a fiber has host nodes below it, we add them to the set.
    • If a fiber has no host nodes below it, we add its closest parent host node to the set.
    • If a fiber has been unmounted, we perform this procedure for its closest still mounted parent instead.
    • If a fiber's parent is root, we use the root host node.

Alternatives

No Component-Specific Visual Feedback

Maybe this is overkill and we just want an indicator in the screen corner or something. Then we can delete this code. I'm not sure and I wanted to play more with this.

Move It Into Consuming Runtime

We could just return affectedFibers and call it a day. Then the consuming code could find the host nodes by copy pasting a similar implementation. That's actually how I started this. However, it's annoying to keep in sync with work tags. And the implementation is a bit tricky (e.g. tracking deletions). So if this is the workflow we want, we'd probably need to centralize it. Why not put it with the rest of the logic we're already testing then? So I put it here.

@sizebot
Copy link

sizebot commented May 20, 2019

ReactDOM: size: 0.0%, gzip: -0.0%

Details of bundled changes.

Comparing: 50b50c2...5b6c10e

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.development.js +0.4% +0.4% 848.29 KB 851.8 KB 193.3 KB 194.12 KB UMD_DEV
react-dom.production.min.js 0.0% -0.0% 105.07 KB 105.07 KB 34.14 KB 34.14 KB UMD_PROD
react-dom.development.js +0.4% +0.4% 842.61 KB 846.12 KB 191.74 KB 192.57 KB NODE_DEV
ReactDOM-dev.js +0.4% +0.4% 868.13 KB 871.71 KB 193.34 KB 194.19 KB FB_WWW_DEV
ReactDOM-profiling.js 0.0% -0.0% 358.16 KB 358.16 KB 66.29 KB 66.29 KB FB_WWW_PROFILING
react-dom-unstable-fire.development.js +0.4% +0.4% 848.64 KB 852.15 KB 193.44 KB 194.27 KB UMD_DEV
react-dom-unstable-fire.production.min.js 0.0% -0.0% 105.09 KB 105.09 KB 34.15 KB 34.15 KB UMD_PROD
react-dom-unstable-fire.development.js +0.4% +0.4% 842.96 KB 846.46 KB 191.88 KB 192.71 KB NODE_DEV
react-dom-unstable-fire.production.min.js 0.0% -0.0% 105.08 KB 105.08 KB 33.59 KB 33.59 KB NODE_PROD
react-dom-unstable-fire.profiling.min.js 0.0% -0.0% 108.44 KB 108.44 KB 34.46 KB 34.46 KB NODE_PROFILING
ReactFire-dev.js +0.4% +0.4% 867.34 KB 870.92 KB 193.28 KB 194.13 KB FB_WWW_DEV
ReactFire-prod.js 0.0% -0.0% 340.96 KB 340.96 KB 62.93 KB 62.93 KB FB_WWW_PROD
ReactFire-profiling.js 0.0% -0.0% 346.11 KB 346.11 KB 63.88 KB 63.88 KB FB_WWW_PROFILING
react-dom-test-utils.production.min.js 0.0% 0.0% 10.76 KB 10.76 KB 3.94 KB 3.95 KB UMD_PROD
react-dom-server.browser.development.js 0.0% 0.0% 137.21 KB 137.21 KB 36.17 KB 36.17 KB UMD_DEV
ReactDOMServer-dev.js 0.0% -0.0% 135.54 KB 135.54 KB 34.8 KB 34.8 KB FB_WWW_DEV
react-dom-server.node.production.min.js 0.0% -0.0% 19.98 KB 19.98 KB 7.53 KB 7.53 KB NODE_PROD
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.81 KB 3.81 KB 1.54 KB 1.54 KB UMD_DEV
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.1% 1.21 KB 1.21 KB 705 B 706 B UMD_PROD
react-dom-unstable-fizz.node.development.js 0.0% -0.1% 3.88 KB 3.88 KB 1.51 KB 1.51 KB NODE_DEV

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.6% +0.7% 584.2 KB 587.7 KB 127.86 KB 128.7 KB UMD_DEV
react-art.production.min.js 0.0% -0.0% 96.76 KB 96.76 KB 29.8 KB 29.8 KB UMD_PROD
react-art.development.js +0.7% +0.8% 515.1 KB 518.61 KB 110.37 KB 111.21 KB NODE_DEV
ReactART-dev.js +0.7% +0.8% 525.5 KB 529.08 KB 109.71 KB 110.55 KB FB_WWW_DEV
ReactART-prod.js 0.0% -0.0% 201.21 KB 201.21 KB 34.29 KB 34.29 KB FB_WWW_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js +0.5% +0.6% 657.77 KB 661.35 KB 140.05 KB 140.92 KB RN_FB_DEV
ReactNativeRenderer-prod.js 0.0% -0.0% 249.18 KB 249.18 KB 43.36 KB 43.36 KB RN_FB_PROD
ReactNativeRenderer-profiling.js 0.0% -0.0% 257.11 KB 257.11 KB 44.97 KB 44.97 KB RN_FB_PROFILING
ReactNativeRenderer-dev.js +0.5% +0.6% 657.68 KB 661.26 KB 140.02 KB 140.89 KB RN_OSS_DEV
ReactNativeRenderer-prod.js 0.0% -0.0% 249.19 KB 249.19 KB 43.36 KB 43.36 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js 0.0% -0.0% 257.12 KB 257.12 KB 44.97 KB 44.97 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.6% +0.6% 646.52 KB 650.1 KB 137.33 KB 138.2 KB RN_FB_DEV
ReactFabric-prod.js 0.0% -0.0% 242.37 KB 242.37 KB 42.02 KB 42.02 KB RN_FB_PROD
ReactFabric-dev.js +0.6% +0.6% 646.43 KB 650.01 KB 137.3 KB 138.17 KB RN_OSS_DEV
ReactFabric-prod.js 0.0% -0.0% 242.38 KB 242.38 KB 42.02 KB 42.02 KB RN_OSS_PROD

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +0.7% +0.8% 528.48 KB 531.99 KB 113.22 KB 114.08 KB UMD_DEV
react-test-renderer.development.js +0.7% +0.7% 524.02 KB 527.53 KB 112.11 KB 112.94 KB NODE_DEV
react-test-renderer.production.min.js 0.0% -0.0% 62.71 KB 62.71 KB 19.25 KB 19.25 KB NODE_PROD
ReactTestRenderer-dev.js +0.7% +0.8% 536.48 KB 540.06 KB 112.19 KB 113.05 KB FB_WWW_DEV

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +0.7% +0.8% 512.21 KB 515.72 KB 108.79 KB 109.63 KB NODE_DEV
react-reconciler-persistent.development.js +0.7% +0.8% 509.89 KB 513.39 KB 107.78 KB 108.63 KB NODE_DEV
react-reconciler-reflection.development.js 0.0% -0.0% 19.16 KB 19.16 KB 6.08 KB 6.08 KB NODE_DEV

Generated by 🚫 dangerJS

gaearon added 3 commits May 20, 2019 20:46
We will return an array of host nodes that are related to the hot reloaded Fibers. The hot reloading implementation can use it to "flash" updated parts of the screen visually.

The array only includes outermost nodes in the updated subtrees. This both helps reduce the overhead from finding host nodes, and avoids overloading the visual feedback. Usually you just want to see the updated area and not every little thing inside of it.

This commit breaks tests. It's because it searches for host nodes that might have been unmounted by the hot update. I will fix this in follow-up commits.
This ensures that when we edit <div> to null, we highlight parent div instead.
This tracks unmounted fibers during a hot reload pass, and temporarily remembers their parent chain.

Even though they get disconnected, this lets us find their closest mounted fibers and search for the visual feedback host node from there.
@gaearon gaearon force-pushed the visual-feedback branch from 204a94a to 5b6c10e Compare May 20, 2019 19:47
@acdlite
Copy link
Collaborator

acdlite commented May 20, 2019

Did you consider using an effect tag? Then you can mutate during the actual commit phase, and you don't need an extra traversal.

@gaearon
Copy link
Collaborator Author

gaearon commented May 22, 2019

This approach is flawed because the visual feedback should happen before the reload is finished. Then it makes sense.

@gaearon gaearon closed this May 22, 2019
@gaearon gaearon deleted the visual-feedback branch May 22, 2019 02:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants