* Restrict effect return type to a function or nothing
We already warn in dev if the wrong type is returned. This updates the
Flow type.
* Restrict return type further
* Assume Effect hook returns either a function or undefined
* Tweak warning message
* Improve Reducer Hook's lazy init API
* Use generic type for initilizer input
Still requires an `any` cast in the case where `init` function is
not provided.
* Move DEV-only function right above where it's used
I don't like looking at this top-level function #petty
* Use different dispatchers for functions & classes
Classes support readContext, but not any of the other dispatcher
methods. Function support all methods.
This is a more robust version of our previous strategy of checking
whether `currentlyRenderingFiber` is null.
As a next step, we can use a separate dispatcher for each phase of the
render cycle (mount versus update).
* Use separate dispatchers for mount and update
* Remove mount code from update path
Deletes mount-specific code from the update path, since it should be
unreachable. To continue supporting progressive enhancement (mounting
new hooks at the end of the list), we detect when there are no more
current hooks and switch back to the mount dispatcher. Progressive
enhancement isn't officially supported yet, so it will continue to warn.
* Factoring nits
* Fix Flow
Had to cheat more than I would like
* More Flow nits
* Switch back to using a special dispatcher for nested hooks in DEV
In order for this strategy to work, I had to revert progressive
enhancement support (appending hooks to the end). It was previously a
warning but now it results in an error. We'll reconsider later.
* Always pass args to updateState and updateReducer
Even though the extra args are only used on mount, to ensure
type consistency.
* Make readContext() in Hooks DEV-only warning
* Warn about readContext() during class render-phase setState()
* Warn on readContext() in SSR inside useMemo and useReducer
* Make all Hooks-in-Hooks warnings DEV-only
* Rename stashContextDependencies
* Clean up warning state on errors
* Turned enableHooks feature flag on everywhere
* Removed useHooks feature flag from tests (now that it's on by default)
* Remove useHooks feature flag entirely
* Rename context variables
I just spent half an hour debugging why readContext(PurpleContext) doesn't work.
* Add test coverage for readContext() on the server
Specifying the directory as part of the `repository` field in a `package.json`
allows third party tools to provide better support when working with monorepos.
For example, it allows them to correctly construct a commit diff for a specific
package.
This format was accepted by npm in https://github.com/npm/rfcs/pull/19.
* Warn when mixing createRoot() and old APIs
* Move container checks to entry points
This way further warning check doesn't crash on bad inputs.
* Fix Flow
* Rename flag to be clearer
* managed by -> passed to
* Revert accidental change
* Fix Fire shim to match
* Don't bother comparing constructor when deps are not provided
When no dependencies are passed to an effect hook, what we used to do is
compare the effect constructor. If there was no change, then we would
skip firing the effect. In practice, this is a useless optimization
because the constructor will always be different when you pass an inline
closure. And if you don't pass an inline closure, then you can't access
any props or state.
There are some edge cases where an effect that doesn't close over props
or state could be useful, like reference counting the number of mounted
components. But those are rare and can be addressed by passing an empty
array of dependencies.
By removing this "optimization," we can avoid retaining the constructor
in the majority of cases where it's a closure that changes on
every render.
I made corresponding changes to the other hooks that accept
dependencies, too (useMemo, useCallback, and useImperativeHandle).
* Improve hook dependencies warning
It now includes the name of the hook in the message.
* Nits
I don't think "array or iterator" is adding anything, and it may well be confusing, especially since this is one of the first and most common warnings that devs see.
* [Fizz] Add Flow/Jest/Rollup build infra
Add a new package for react-stream which allows for custom server renderer
outputs. I picked the name because it's a reasonable name but also
because the npm name is currently owned by a friend of the project.
The react-dom build has its own inlined server renderer under the
name `react-dom/fizz`.
There is also a noop renderer to be used for testing. At some point
we might add a public one to test-renderer but for now I don't want to have
to think about public API design for the tests.
* Add FormatConfig too
We need to separate the format (DOM, React Native, etc) from the host
running the server (Node, Browser, etc).
* Basic wiring between Node, Noop and DOM configs
The Node DOM API is pipeToNodeStream which accepts a writable stream.
* Merge host and format config in dynamic react-stream entry point
Simpler API this way but also avoids having to fork the wrapper config.
Fixes noop builds.
* Add setImmediate/Buffer globals to lint config
Used by the server renderer
* Properly include fizz.node.js
Also use forwarding to it from fizz.js in builds so that tests covers
this.
* Make react-stream private since we're not ready to publish
or even name it yet
* Rename Renderer -> Streamer
* Prefix react-dom/fizz with react-dom/unstable-fizz
* Add Fizz Browser host config
This lets Fizz render to WHATWG streams. E.g. for rendering in a
Service Worker.
I added react-dom/unstable-fizz.browser as the entry point for this.
Since we now have two configurations of DOM. I had to add another
inlinedHostConfigs configuration called `dom-browser`. The reconciler
treats this configuration the same as `dom`. For stream it checks
against the ReactFizzHostConfigBrowser instead of the Node one.
* Add Fizz Browser Fixture
This is for testing server rendering - on the client.
* Lower version number to detach it from react-reconciler version
useMutationEffect has problems (namely, refs aren't attached at the time that it runs) and we're not positive it's necessary. useLayoutEffect runs at the same time as componentDidMount/Update so it's sufficient for all existing use cases; it can be used in any case that useEffect happens too late. Until we figure out what we want to do, let's delete it.
Regression introduced in #14182 resulted in errors no longer being emitted on streams, breaking many consumers.
Co-authored-by: Elliot Jalgard <elliot.j@live.se>
Whenever we do this, Rollup needs to materialize this as an object.
This causes it to also add the Babel compatibility property which is
unnecessary bloat. However, since when we use these, we leak the object
this often also deopts any compiler optimizations.
If we really need an object we should export default an object.
Currently there is an exception for DOMTopLevelEventTypes since
listing out the imports is a PITA and it doesn't escape so it should
get properly inlined. We should probably move to a different pattern
to avoid this for consistency though.
Disables the recently introduced (#14181) warning for shorthand
CSS property collisions by wrapping in a feature flag. Let's hold off
shipping this until at least the next minor.
I figured out a simpler way to do #14181. It does allocate some but I think that's OK. Time complexity might even be better since we avoid the nested loops the old one had.
* BUG: ReactPartialRenderer / New Context polutes mutable global state
The new context API stores the provided values on the shared context instance. When used in a synchronous context, this is not an issue. However when used in an concurrent context this can cause a "push provider" from one react render to have an effect on an unrelated concurrent react render.
I've encountered this bug in production when using renderToNodeStream, which asks ReactPartialRenderer for bytes up to a high water mark before yielding. If two Node Streams are created and read from in parallel, the state of one can polute the other.
I wrote a failing test to illustrate the conditions under which this happens.
I'm also concerned that the experimental concurrent/async React rendering on the client could suffer from the same issue.
* Use unique thread ID for each partial render to access Context
This first adds an allocator that keeps track of a unique ThreadID index
for each currently executing partial renderer. IDs are not just growing
but are reused as streams are destroyed.
This ensures that IDs are kept nice and compact.
This lets us use an "array" for each Context object to store the current
values. The look up for these are fast because they're just looking up
an offset in a tightly packed "array".
I don't use an actual Array object to store the values. Instead, I rely
on that VMs (notably V8) treat storage of numeric index property access
as a separate "elements" allocation.
This lets us avoid an extra indirection.
However, we must ensure that these arrays are not holey to preserve this
feature.
To do that I store the _threadCount on each context (effectively it takes
the place of the .length property on an array).
This lets us first validate that the context has enough slots before we
access the slot. If not, we fill in the slots with the default value.
This is one of the most insidious quirks of React DOM that people run into. Now we warn when we think an update is dangerous.
We still allow rendering `{background, backgroundSize}` with unchanging values, for example. But once you remove either one or change `background` (without changing `backgroundSize` at the same time), that's bad news. So we warn.
Fixes#6348.
* Recover from errors with a boundary in completion phase
* Use a separate field for completing unit of work
* Use a simpler fix with one boolean
* Reoder conditions
* Clarify which paths are DEV-only
* Move duplicated line out
* Make it clearer this code is DEV-only
Setting to null isn't correct; setting to '' is. I opted to use dangerousStyleValue for consistency with the main path that we set things.
Fixes#14114.
Test Plan:
Verified setting to '' works in Chrome and IE11. (Setting to null works in Chrome but not in IE11.)