Commit Graph
13210 Commits
Author SHA1 Message Date
Sebastian Markbåge edf6eac8a1 Don't cut off the tail of a SuspenseList if hydrating (#18854) 2020-05-06 23:51:46 -07:00
Sebastian Markbåge 55f5cdee01 Disable setState before mount in legacy mode (#18851)
We kind of "support" this pattern in legacy mode. It's only deprecated in
Concurrent Mode.
2020-05-06 20:30:59 -07:00
Andrew Clark 47ebc90b08 Put render phase update change behind a flag (#18850)
In the new reconciler, I made a change to how render phase updates
work. (By render phase updates, I mean when a component updates
another component during its render phase. Or when a class component
updates itself during the render phase. It does not include when
a hook updates its own component during the render phase. Those have
their own semantics. So really I mean anything triggers the "`setState`
in render" warning.)

The old behavior is to give the update the same "thread" (expiration
time) as whatever is currently rendering. So if you call `setState` on a
component that happens later in the same render, it will flush during
that render. Ideally, we want to remove the special case and treat them
as if they came from an interleaved event.

Regardless, this pattern is not officially supported. This behavior is
only a fallback. The flag only exists until we can roll out the
`setState` warnning, since existing code might accidentally rely on the
current behavior.
2020-05-06 19:19:14 -07:00
Dominic Gannaway 6778c53c16 Modern Event System: fix bug in EnterLeave (#18849) 2020-05-07 00:13:13 +01:00
Brian Vaughn 7eaa1d7e33 Updated DevTools unstable_ API references (#18847) 2020-05-06 11:14:30 -07:00
Andrew Clark a71aa803a1 [Release] Follow redirect when downloading tarball (#18845)
Adds -L option to `curl` command.

See: https://curl.haxx.se/docs/manpage.html#-L
2020-05-06 10:28:49 -07:00
Sebastian Markbåge 96f3b7d1c3 Warn if calling setState outside of render but before commit (#18838)
* Don't attempt to render the children of a dehydrated Suspense boundary

The DehydratedFragment tag doesn't exist so doing so throws.

This can happen if we schedule childExpirationTime on the boundary and
bail out.

* Warn if scheduling work on a component before it is committed
2020-05-06 09:45:35 -07:00
Dan Abramov 33c3af284c [Blocks Fixture] Remove remaining Blocks (#18840) 2020-05-06 15:53:51 +01:00
Dan Abramov 595d27bd73 [Blocks Fixture] Drop the Blocks (#18837)
* [Blocks Fixture] Add a tiny router

* Add a way to load nested entrypoint

* Only expose URL params to nested routers

* Add keys to route definitions

* [Blocks Fixture] Drop the Blocks
2020-05-06 05:17:44 +01:00
Dominic Gannaway 823dc581fe Modern Event System: fix EnterLeave plugin logic (#18830) 2020-05-05 22:10:07 +01:00
Fernando Lores 40e6029462 wrap SuspenseInstanceRetry callback so scheduler waits for it (#18805) 2020-05-05 12:47:49 -07:00
Brian Vaughn 3cde22a84e Experimental test selector API (#18607)
Adds several new experimental APIs to aid with automated testing.

Each of the methods below accepts an array of "selectors" that identifies a path (or paths) through a React tree. There are four basic selector types:

* Component: Matches Fibers with the specified React component type
* Role: Matches Host Instances matching the (explicit or implicit) accessibility role.
* Test name: Matches Host Instances with a data-testname attribute.
* Text: Matches Host Instances that directly contain the specified text.
* There is also a special lookahead selector type that enables further matching within a path (without actually including the path in the result). This selector type was inspired by the :has() CSS pseudo-class. It enables e.g. matching a <section> that contained a specific header text, then finding a like button within that <section>.

API
* findAllNodes(): Finds all Host Instances (e.g. HTMLElement) within a host subtree that match the specified selector criteria.
* getFindAllNodesFailureDescription(): Returns an error string describing the matched and unmatched portions of the selector query.
* findBoundingRects(): For all React components within a host subtree that match the specified selector criteria, return a set of bounding boxes that covers the bounds of the nearest (shallowed) Host Instances within those trees.
* observeVisibleRects(): For all React components within a host subtree that match the specified selector criteria, observe if it’s bounding rect is visible in the viewport and is not occluded.
* focusWithin(): For all React components within a host subtree that match the specified selector criteria, set focus within the first focusable Host Instance (as if you started before this component in the tree and moved focus forwards one step).
2020-05-05 10:37:46 -07:00
Dan Abramov c13a59c7d6 Fix Blocks fixture 2020-05-05 18:14:06 +01:00
Kevin Lewis 7992ca10df eslint-plugin-react-hooks: allow OptionalMemberExpression in deps (#18819) (#18820)
* eslint-plugin-react-hooks: allow OptionalMemberExpression in deps (#18819)

* add test case for #18819

* fix test

* run prettier
2020-05-05 13:53:42 +01:00
Dominic Gannaway e028ce2ab7 Modern Event System: ensure target ancestors are only host nodes (#18827) 2020-05-05 13:10:05 +01:00
Dan Abramov 4d124a4f67 [Blocks Fixture] Misc updates (#18811)
* [Blocks Fixture] Update navigation buttons immediately

* Add more profile links

* Minor refactor

* Add subroutes to Profile
2020-05-05 11:53:02 +01:00
Andrew Clark fe7163e73d Add unstable prefix to experimental APIs (#18825)
We've been shipping unprefixed experimental APIs (like `createRoot` and
`useTransition`) to the Experimental release channel, with the rationale
that because these APIs do not appear in any stable release, we're free
to change or remove them later without breaking any downstream projects.

What we didn't consider is that downstream projects might be tempted to
use feature detection:

```js
const useTransition = React.useTransition || fallbackUseTransition;
```

This pattern assumes that the version of `useTransition` that exists in
the Experimental channel today has the same API contract as the final
`useTransition` API that we'll eventually ship to stable.

To discourage feature detection, I've added an `unstable_` prefix to
all of our unstable APIs.

The Facebook builds still have the unprefixed APIs, though. We will
continue to support those; if we make any breaking changes, we'll
migrate the internal callers like we usually do. To make testing easier,
I added the `unstable_`-prefixed APIs to the www builds, too. That way
our tests can always use the prefixed ones without gating on the
release channel.
2020-05-04 22:25:41 -07:00
Sebastian Markbåge cd4a96035f Remove old CM exports (#18710) 2020-05-04 21:39:57 -07:00
Dominic Gannaway 9751935abf Modern Event System: improve dispatching queue (#18799) 2020-05-04 16:55:45 +01:00
Dan Abramov 3e13d70984 [RN] Remove debugging invariant (#18813) 2020-05-04 15:48:35 +01:00
Dan Abramov f6fcae58e9 [Blocks] Add Shell to Fixture (#18803)
* [Blocks] Add Feed page to fixture

* Add minimal routing

* Always show post with comments
2020-05-04 01:59:55 +01:00
Dan Abramov d830cd9984 [Blocks] Fix stale data on updates (#18810)
* [Blocks] Failing test for nested load

* Simplify the test

* Add a similar test that fails in PROD

* Copy .type when cloning work in progress
2020-05-04 01:43:51 +01:00
Sebastian Markbåge 64d4b84204 Rename Flight to Transport (#18808)
* Rename Flight to Transport

Flight is still the codename for the implementation details (like Fiber).

However, now the public package is react-transport-... which is only
intended to be used directly by integrators.

* Rename names
2020-05-03 11:33:48 -07:00
Andrew Clark 93e078ddf2 Initial Lanes implementation (#18796)
See PR #18796 for more information.

All of the changes I've made in this commit are behind the
`enableNewReconciler` flag. Merging this to master will not affect the
open source builds or the build that we ship to Facebook.

The only build that is affected is the `ReactDOMForked` build, which is
deployed to Facebook **behind an experimental flag (currently disabled
for all users)**. We will use this flag to gradually roll out the new
reconciler, and quickly roll it back if we find any problems.

Because we have those protections in place, what I'm aiming for with
this initial PR is the **smallest possible atomic change that lands
cleanly and doesn't rely on too many hacks**. The goal has not been to
get every single test or feature passing, and it definitely is not to
implement all the features that we intend to build on top of the new
model. When possible, I have chosen to preserve existing semantics and
defer changes to follow-up steps. (Listed in the section below.)

(I did not end up having to disable any tests, although if I had, that
should not have necessarily been a merge blocker.)

For example, even though one of the primary goals of this project is to
improve our model for parallel Suspense transitions, in this initial
implementation, I have chosen to keep the same core heuristics for
sequencing and flushing that existed in the ExpirationTimes model: low
priority updates cannot finish without also finishing high priority
ones.

Despite all these precautions, **because the scope of this refactor is
inherently large, I do expect we will find regressions.** The flip side
is that I also expect the new model to improve the stability of the
codebase and make it easier to fix bugs when they arise.
2020-05-02 17:09:31 -07:00
Moti ZilbermanandSebastian Markbage 3c7d52c3d6 Give unresolved lazy() a name in component stack (#16104)
* Give unresolved lazy() a name in component stack

* Normalize stack in tests

Co-authored-by: Sebastian Markbage <sema@fb.com>
2020-05-01 16:41:39 -07:00
Benedikt Franke 333deb707d Remove hint to post feedback about exhaustive-deps rule (#18712)
The thread is closed and locked.
2020-05-01 19:13:59 +01:00
Dominic Gannaway aa88589d0b Refine experimental Scopes API (#18778)
* Refine experimental Scopes API
2020-05-01 19:01:43 +01:00
Dan Abramov d804f99b9e eslint-plugin-react-hooks@4.0.0 2020-05-01 17:13:56 +01:00
Dan Abramov 4e93b9364c Add changelog for eslint-plugin-react-hooks (#18801) 2020-05-01 17:12:32 +01:00
Aaron PettengillandAaron Pettengill 5ac9ca72df Feature: Add support to exhaustive-deps rule for any hook ending with Effect (#18580)
* Add test cases for support exhaustive deps ending in Effect

* Apply the exhaustive deps lint rule to any hook ending with Effect

* Add another test for supporting linting useXEffect hooks

Co-authored-by: Aaron Pettengill <aaron.pettengill@echoman.com>
2020-05-01 16:57:25 +01:00
Dan Abramov eab94403d7 Build Flight runtime for WWW (revert part of earlier change) 2020-05-01 16:44:25 +01:00
Sebastian Markbåge 17dcc29cd1 Don't "schedule" discrete work if we're scheduling sync work (#18797) 2020-05-01 08:43:15 -07:00
Dan Abramov 9491f39472 react-refresh@0.8.2 2020-05-01 16:18:13 +01:00
Dan Abramov 43a1c72751 Don't build react-data for WWW 2020-05-01 16:13:11 +01:00
Dan Abramov 01914a7673 Update bundle configs to not build some packages (#18800)
* Stop building old ReactCache for FB

* Update other bundle configs
2020-05-01 16:07:36 +01:00
Sophie Alpert 21670cf4be [react-refresh/babel] Always insert registrations after var (#18794)
Previously, we transformed

```
let Foo = styled.div``;
```

to

```
let Foo = _c1 = styled.div``;
```

and then babel-plugin-styled-components would infer `_c1` as the display name. Widen the existing case that applies to function expressions to apply to any type of variable declaration.
2020-05-01 16:01:11 +01:00
Andrew Clark 914b57be27 Move legacy hidden API to new internal Fiber type (#18782)
* Unhide Suspense trees without entanglement

When a Suspense boundary is in its fallback state, you cannot switch
back to the main content without also finishing any updates inside the
tree that might have been skipped. That would be a form of tearing.

Before we fixed this in #18411, the way this bug manifested was that a
boundary was suspended by an update that originated from a child
component (as opposed to props from a parent). While the fallback was
showing, it received another update, this time at high priority. React
would render the high priority update without also including the
original update. That would cause the fallback to switch back to the
main content, since the update that caused the tree to suspend was no
longer part of the render. But then, React would immediately try to
render the original update, which would again suspend and show the
fallback, leading to a momentary flicker in the UI.

The approach added in #18411 is, when receiving a high priority update
to a Suspense tree that's in its fallback state is to bail out, keep
showing the fallback and finish the update in the rest of the tree.
After that commits, render again at the original priority. Because low
priority expiration times are inclusive of higher priority expiration
times, this ensures that all the updates are committed together.

The new approach in this commit is to turn `renderExpirationTime` into a
context-like value that lives on the stack. Then, when unhiding the
Suspense boundary, we can push a new `renderExpirationTime` that is
inclusive of both the high pri update and the original update that
suspended. Then the boundary can be unblocked in a single render pass.

An advantage of the old approach is that by deferring the work of
unhiding, there's less work to do in the high priority update.

The key advantage of the new approach is that it solves the consistency
problem without having to entangle the entire root.

* Create internal LegacyHidden type

This only exists so we can clean up the internal implementation of
`<div hidden={isHidden} />`, which is not a stable feature. The goal
is to move everything to the new Offscreen type instead. However,
Offscreen has different semantics, so before we can remove the legacy
API, we have to migrate our internal usage at Facebook. So we'll need
to maintain both temporarily.

In this initial commit, I've only added the type. It's not used
anywhere. The next step is to use it to implement `hidden`.

* Use LegacyHidden to implement old hidden API

If a host component receives a `hidden` prop, we wrap its children in
an Offscreen fiber. This is similar to what we do for Suspense children.

The LegacyHidden type happens to share the same implementation as the
new Offscreen type, for now, but using separate types allows us to fork
the behavior later when we implement our planned changes to the
Offscreen API.

There are two subtle semantic changes here. One is that the children of
the host component will have their visibility toggled using the same
mechanism we use for Offscreen and Suspense: find the nearest host node
children and give them a style of `display: none`. We didn't used to do
this in the old API, because the `hidden` DOM attribute on the parent
already hides them. So with this change, we're actually "overhiding" the
children. I considered addressing this, but I figure I'll leave it as-is
in case we want to expose the LegacyHidden component type temporarily
to ease migration of Facebook's internal callers to the Offscreen type.

The other subtle semantic change is that, because of the extra fiber
that wraps around the children, this pattern will cause the children
to lose state:

```js
return isHidden ? <div hidden={true} /> : <div />;
```

The reason is that I didn't want to wrap every single host component
in an extra fiber. So I only wrap them if a `hidden` prop exists. In
the above example, that means the children are conditionally wrapped
in an extra fiber, so they don't line up during reconciliation, so
they get remounted every time `isHidden` changes.

The fix is to rewrite to:

```js
return <div hidden={isHidden} />;
```

I don't anticipate this will be a problem at Facebook, especially since
we're only supposed to use `hidden` via a userspace wrapper component.
(And since the bad pattern isn't very React-y, anyway.)

Again, the eventual goal is to delete this completely and replace it
with Offscreen.
2020-04-30 19:37:27 -07:00
Brian Vaughn ac533fde3d Prevent stale legacy root from clearing a container (DRAFT) (#18792)
* Don't clear a container because of a stale legacy root

* Added test repro for FB error
2020-04-30 15:56:21 -07:00
Dan Abramov 5b89d353e2 Update react-refresh README 2020-04-30 15:43:21 +01:00
Dan Abramov 3a9c373521 [Blocks] Add preload to fetch (#18785) 2020-04-30 02:23:18 +01:00
Dan Abramov dd7f0deb94 [Blocks] Use native fetch (#18784)
* [Blocks] Use native fetch

* Use the prototype

* Support arrayBuffer() and blob()

* ctor

* Simplify

* Use an expando

* Keep a map of formats

* Unused

* Remove unnecessary second property read

* Keep it simple

* Store the original thenable
2020-04-30 01:24:04 +01:00
Alex Taylor e71f5df9c3 Consistent useCallback implementation in ReactDOMServer (#18783) 2020-04-29 16:22:10 -07:00
Dan Abramov 515326753b [Blocks] Initial implementation of cache and data/fetch (#18774)
* Rename ReactCache -> ReactCacheOld

We still use it in some tests so I'm going to leave it for now. I'll start making the new one in parallel in the react package.

* Add react/unstable-cache entry point

* Add react-data entry point

* Initial implementation of cache and data/fetch

* Address review
2020-04-29 19:14:15 +01:00
Dan Abramov 53d68b33ff [Blocks] Add Client Fixture (#18773)
* [Blocks] Add Client Fixture

* Add more TODOs
2020-04-29 02:23:09 +01:00
Dominic Gannaway 88d0be6da5 Refactor ElementListenerMap (#18766) 2020-04-28 21:53:51 +01:00
Brian Vaughn ea2af878cc Root API should clear non-empty roots before mounting (#18730)
* Root API should clear non-empty roots before mounting

Legacy render-into-subtree API removes children from a container before rendering into it. The root API did not do this previously, but just left the children around in the document.

This commit adds a new FiberRoot flag to clear a container's contents before mounting. This is done during the commit phase, to avoid multiple, observable mutations.
2020-04-28 13:07:42 -07:00
Nick Reiley d2ef120089 Allow Node 14.x (#18755) 2020-04-28 15:57:45 +01:00
Sebastian Markbåge 53ce0c3452 Allow flushSync to noop in life cycles but with a warning (#18759) 2020-04-27 20:07:39 -07:00
Andrew Clark f342a2399f SuspenseList: Reschedule at same priority (#18738)
SuspenseList progressively renders items even if the list is CPU bound,
i.e. it isn't waiting for missing data. It does this by showing a
fallback for the remaining items, committing the items in that have
already finished, then starting a new render to continue working on
the rest.

When it schedules that subsequent render, it uses a slightly lower
priority than the current render: `renderExpirationTime - 1`.

This commit changes it to reschedule at `renderExpirationTime` instead.

I don't know what the original motivation was for bumping the expiration
time slightly lower. The comment says that the priorities of the two
renders are the same (which makes sense to me) so I imagine it was
motivated by some implementation detail. I don't think it's necessary
anymore, though perhaps it was when it was originally written. If it is
still necessary, we should write a test case that illustrates why.
2020-04-25 20:27:35 -07:00
Andrew Clark cb70753993 Move hide/unhide logic to Offscreen component
The Offscreen component is not a public type, yet, but once it is, it
will share the same hide/unhide logic as Suspense children.
2020-04-25 00:10:09 -07:00