React: Implement additional async APIs in preparation for v16

Created on 18 Jul 2017  路  11Comments  路  Source: facebook/react

  • [x] ReactDOM/ReactNative.activeUpdates. Similar to what we currently call ReactDOM.unstable_syncUpdates except updates are batched, and flushed at the end of the batch regardless of whether it's nested inside batchedUpdates. (#10225)
  • [x] Opt-in subtree to async mode

    • [x] Static flag on class components (unstable_asyncUpdates)

    • [x] <React.unstable_Async /> component type

Items we're considering for minor 16 releases, but have decided not to ship in 16.0:

  • Commit phase version of willMount/willUpdate (fires even for any deep set state in the subtree, and replaces the global prepareForCommit/resetAfterCommit host configs)
  • Passive versions of didMount/didUpdate

All 11 comments

ReactDOM/ReactNative.activeUpdates

Is that a "stable" API? The annoying thing about those APIs has always been that they hang from renderers. So universal components can't use them easily without importing both renderers or dependency injection. Is this something we want to solve?

It would be kind of difficult to implement as an isomorphic API because presumably multiple renderers will all need to add listeners to a growing set and then all flush together. I think at the very least it requires global mutable state and might be unnecessarily bloated/slow.

We talked ourselves into that this won't actually be a problem with activeUpdates as it was with batchedUpdates because batchedUpdates was used to add more batching where as activeUpdates is used to get less batching. The use case for activeUpdates is more about integrating with imperative APIs directly such as directly with animation APIs or controlled components. As such it'll know more about the environment it is being used.

It is actually a bad idea to use this with generic Flux-like libraries because in async mode they're already batched by default. If you want to use activeUpdates, it is an indicator that the library doesn't support async mode and should probably be redesigned to support it. So it's more of a legacy thing in that case.

A down-side is that the React renderer implementation is no longer swappable for these. :/

It is "stable" because the activeness of the ReactDOM/Native.activeUpdates() call is expected to be stable but the asyncness of the subtree (the unstable_asyncUpdates flag) is expected to be unstable.

That makes a lot of sense, thanks.

So as long as we're in compat mode activeUpdates is effectively a no-op, but it takes meaning when you opt into async?

So as long as we're in compat mode activeUpdates is effectively a no-op?

Almost...

this.setState(A);
ReactDOM.activeUpdates(() => {
  this.setState(B);
  this.setState(C);
});
this.setState(D);

In sync mode, effect is that B and C are batched. In async mode, effect is that B and C have task priority.

Specifically activeUpdates guarantees to flush all task work before it ends.

batchedUpdates(() => {
  this.setState(A);
  activeUpdates(() => {
    this.setState(B);
    this.setState(C);
  }); // flushes A, B, C
  this.setState(D);
}); // flushes D

Unlike nested batchedUpdates which doesn't.

So it's not the same as noop.

Just discussed offline a bit. The ideal behavior is that B and C flush but A does not, which means we need multiple levels of active-ness. Kind of like how we need multiple levels of hidden/offscreen priority.

For now, we'll disallow nested activeUpdates, since that's likely an edge case.

@acdlite This example doesn't have nested activeUpdates, but it does have a batchedUpdates outside the activeUpdates. That might be more common.

True... The most common batchedUpdates case is event handlers, right? Which are active by default for now, anyway, so activeUpdates shouldn't be necessary?

Hm. They're not active right now are they? Maybe add that to the list? I'm not sure all should be. E.g. load might not need to be sync by default.

Oh, I thought they were. Yeah we should figure that out before 16.

Was this page helpful?
0 / 5 - 0 ratings