## Summary
Now that React Native owns the definition for public instances in Fabric
and ReactNativePrivateInterface provides the methods to create instances
and access private fields (see
https://github.com/facebook/react-native/pull/36570), we can remove the
definitions from React.
After this PR, React Native public instances will be opaque types for
React and it will only handle their creation but not their definition.
This will make RN similar to DOM in how public instances are handled.
This is a new version of #26418 which was closed without merging.
## How did you test this change?
* Existing tests.
* Manually synced the changes in this PR to React Native and tested it
end to end in Meta's infra.
DiffTrain build for commit https://github.com/facebook/react/commit/9c54b29b44d24f8f8090da9c7ebf569747a444df.
## Overview
This PR unfortunately removes the warning emitted when using layout
effects on the server:
> useLayoutEffect does nothing on the server, because its effect cannot
be encoded into the server renderer's output format. This will lead to a
mismatch between the initial, non-hydrated UI and the intended UI. To
avoid this, useLayoutEffect should only be used in components that
render exclusively on the client. See
https://reactjs.org/link/uselayouteffect-ssr for common fixes.
## Why this warning exists
The new docs explain this really well. Adding a screenshot because as
part of this change, we'll be removing these docs.
<img width="1562" alt="Screenshot 2023-03-15 at 10 56 17 AM"
src="https://user-images.githubusercontent.com/2440089/225349148-f0e57c3f-95f5-4f2e-9178-d9b9b221c28d.png">
## Why are we changing it
In practice, users are not just ignoring this warning, but creating
hooks to bypass this warning by switching the useLayoutEffect hook on
the server instead of fixing it. This battle seems to be lost, so let's
remove the warning so at least users don't need to use the indirection
hook any more. In practice, if it's an issue, you should see the
problems like flashing the wrong content on first load in development.
DiffTrain build for commit https://github.com/facebook/react/commit/f77099b6f1ccc658eff3467c6b9337e1b77ec854.
Fixes a bug in SuspenseList that @kassens found when deploying React to
Meta. In some scenarios, SuspenseList would force the fallback of a
deeply nested Suspense boundary into fallback mode, which should never
happen under any circumstances — SuspenseList should only affect the
nearest descendent Suspense boundaries, without going deeper.
The cause was that the internal ForceSuspenseFallback context flag was
not being properly reset when it reached the nearest Suspense boundary.
It should only be propagated shallowly.
We didn't discover this earlier because the scenario where it happens is
not that common. To trigger the bug, you need to insert a new Suspense
boundary into an already-mounted row of the list. But often when a new
Suspense boundary is rendered, it suspends and shows a fallback, anyway,
because its content hasn't loaded yet.
Another reason we didn't discover this earlier is because there was
another bug that was accidentally masking it, which was fixed by #25922.
When that fix landed, it revealed this bug.
The SuspenseList implementation is complicated but I'm not too concerned
with the current messiness. It's an experimental API, and we intend to
release it soon, but there are some known flaws and missing features
that we need to address first regardless. We'll likely end up rewriting
most of it.
Co-authored-by: Jan Kassens <jkassens@meta.com>
DiffTrain build for commit https://github.com/facebook/react/commit/51a7c45f8799cab903693fcfdd305ce84ba15273.
## Summary
This type was defined as `mixed` to avoid bringing the whole definition
from React to React Native, but its definition is visible to RN. This
type should be opaque to RN, so this makes it explicit.
## How did you test this change?
Applied the same changes in the React Native repository and could use
the type without issues.
DiffTrain build for commit https://github.com/facebook/react/commit/8e17bfd144f1794398b2cb37ccfbd2cfcb844566.
(This was reviewed and approved as part of #26380; I'm extracting it
into its own PR so that it can bisected later if it causes an issue.)
I noticed while working on a PR that when an error happens during
hydration, and we revert to client rendering, React actually does _two_
additional render passes instead of just one. We didn't notice it
earlier because none of our tests happened to assert on how many renders
it took to recover, only on the final output.
It's possible this extra render pass had other consequences that I'm not
aware of, like messing with some assumption in the recoverable errors
logic.
This adds a test to demonstrate the issue. (One problem is that we don't
have much test coverage of this scenario in the first place, which
likely would have caught this earlier.)
DiffTrain build for commit https://github.com/facebook/react/commit/77ba1618a528787baaa8e007fadaff93a86fb675.
This is in line with the refactor I already did on Fizz earlier and
brings Fiber up to a similar structure.
We end up with a lot of extra checks due the extra abstractions we use
to check the various properties. This uses a flatter and more inline
model which makes it easier to see what each property does. The tradeoff
is that a change might need changes in more places.
The general structure is that there's a switch for tag first, then a
switch for each attribute special case, then a switch for the value. So
it's easy to follow where each scenario will end up and there shouldn't
be any unnecessary code executed along the way.
My goal is to eventually get rid of the meta-programming in DOMProperty
and CSSProperty but I'm leaving that in for now - in line with Fizz.
My next step is moving around things a bit in the diff/commit phases.
This is the first step to more refactors for perf and size, but also
because I'm adding more special cases so I need to have a flatter
structure that I can reason about for those special cases.
DiffTrain build for commit https://github.com/facebook/react/commit/520f7f3ed4d01e9e50a73d7d04ff138e3c71ac86.
When rendering a suspensey resource that we haven't seen before, it may
have loaded in the background while we were rendering. We should yield
to the main thread to see if the load event fires in an immediate task.
For example, if the resource for a link element has already loaded, its
load event will fire in a task right after React yields to the main
thread. Because the continuation task is not scheduled until right
before React yields, the load event will ping React before it resumes.
If this happens, we can resume rendering without showing a fallback.
I don't think this matters much for images, because the `completed`
property tells us whether the image has loaded, and during a non-urgent
render, we never block the main thread for more than 5ms at a time (for
now — we might increase this in the future). It matters more for
stylesheets because the only way to check if it has loaded is by
listening for the load event.
This is essentially the same trick that `use` does for userspace
promises, but a bit simpler because we don't need to replay the host
component's begin phase; the work-in-progress fiber already completed,
so we can just continue onto the next sibling without any additional
work.
As part of this change, I split the `shouldSuspendCommit` host config
method into separate `maySuspendCommit` and `preloadInstance` methods.
Previously `shouldSuspendCommit` was used for both.
This raised a question of whether we should preload resources during a
synchronous render. My initial instinct was that we shouldn't, because
we're going to synchronously block the main thread until the resource is
inserted into the DOM, anyway. But I wonder if the browser is able to
initiate the preload even while the main thread is blocked. It's
probably a micro-optimization either way because most resources will be
loaded during transitions, not urgent renders.
DiffTrain build for commit https://github.com/facebook/react/commit/0131d0cff40d4054ac72c857d3a13c5173c46e0a.
## Summary
We are going to move the definition of public instances from React to
React Native to have them together with the native methods in Fabric
that they invoke. This will allow us to have a better type safety
between them and iterate faster on the implementation of this proposal:
https://github.com/react-native-community/discussions-and-proposals/pull/607
The interface between React and React Native would look like this after
this change and a following PR (#26418):
React → React Native:
```javascript
ReactNativePrivateInterface.createPublicInstance // to provide via refs
ReactNativePrivateInterface.getNodeFromPublicInstance // for DevTools, commands, etc.
ReactNativePrivateInterface.getNativeTagFromPublicInstance // to implement `findNodeHandle`
```
React Native → React (ReactFabric):
```javascript
ReactFabric.getNodeFromInternalInstanceHandle // to get most recent node to call into native
ReactFabric.getPublicInstanceFromInternalInstanceHandle // to get public instances from results from native
```
## How did you test this change?
Flow
Existing unit tests
DiffTrain build for commit https://github.com/facebook/react/commit/3554c8852fe209ad02380ebd24d32f56d6399906.