Files
react/scripts/error-codes/codes.json

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

550 lines
60 KiB
JSON
Raw Normal View History

{
"0": "Encountered an invalid child; DOM elements are not valid children of React components.",
"1": "update(): expected target of %s to be an array; got %s.",
"2": "update(): expected spec of %s to be an array; got %s. Did you forget to wrap your parameter in an array?",
"3": "update(): You provided a key path to update() that did not contain one of %s. Did you forget to include {%s: ...}?",
"4": "Cannot have more than one key in an object with %s",
"5": "update(): %s expects a spec of type 'object'; got %s",
"6": "update(): %s expects a target of type 'object'; got %s",
"7": "Expected %s target to be an array; got %s",
"8": "update(): expected spec of %s to be an array of arrays; got %s. Did you forget to wrap your parameters in an array?",
"9": "update(): expected spec of %s to be a function; got %s.",
"10": "instance must be a composite component",
"11": "TestUtils.scryRenderedDOMComponentsWithClass expects a className as a second argument.",
"12": "ReactShallowRenderer render(): Invalid component element.%s",
"13": "ReactShallowRenderer render(): Shallow rendering works only with custom components, not primitives (%s). Instead of calling `.render(el)` and inspecting the rendered output, look at `el.props` directly instead.",
"14": "TestUtils.Simulate expects a component instance and not a ReactElement.TestUtils.Simulate will not work if you are using shallow rendering.",
"15": "instance must be a composite component",
"16": "Do not override existing functions.",
"17": "All native instances should have a tag.",
"18": "Expected a component class, got %s.%s",
"19": "Expect a native root tag, instead got %s",
"20": "RawText \"%s\" must be wrapped in an explicit <Text> component.",
"21": "Argument is not a component (type: %s, keys: %s)",
"22": "Unable to find node handle for unmounted component.",
"23": "onlyChild must be passed a children with exactly one child.",
"24": "Mismatched list of contexts in callback queue",
"25": "Trying to release an instance into a pool of a different type.",
"26": "Unexpected node: %s",
"27": "Cannot initialize a transaction when there is already an outstanding transaction.",
"28": "Transaction.closeAll(): Cannot close transaction when none are open.",
"29": "Accumulated items must be not be null or undefined.",
"30": "Accumulated items must not be null or undefined.",
"31": "Objects are not valid as a React child (found: %s). If you meant to render a collection of children, use an array instead.",
"32": "Unable to find element with ID %s.",
"33": "getNodeFromInstance: Invalid argument.",
"34": "React DOM tree root should always have a node reference.",
"35": "isAncestor: Invalid argument.",
"36": "getParentInstance: Invalid argument.",
"37": "_Target container is not a DOM element.",
"38": "parentComponent must be a valid React Component",
"39": "ReactDOM.render(): Invalid component element.%s",
"40": "Target container is not a DOM element.",
"41": "Target container is not valid.",
"42": "You're trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure. React cannot handle this case due to cross-browser quirks by rendering at the document root. You should look for environment dependent code in your components and ensure the props are the same client and server side:\n%s",
"43": "You're trying to render a component to the document but you didn't use server rendering. We can't do this without using server rendering due to cross-browser quirks. See ReactDOMServer.renderToString() for server rendering.",
"44": "findDOMNode was called on an unmounted component.",
"45": "Element appears to be neither ReactComponent nor DOMNode (keys: %s)",
"46": "renderToString(): You must pass a valid ReactElement.",
"47": "renderToStaticMarkup(): You must pass a valid ReactElement.",
"48": "You're trying to inject DOM property '%s' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.",
"49": "DOMProperty: Properties that have side effects must use property: %s",
"50": "DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s",
"51": "Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString for server rendering.",
"52": "Missing markup.",
"53": "Danger: Assigning to an already-occupied result index.",
"54": "Danger: Did not assign to every index of resultList.",
"55": "Danger: Expected markup to render %s nodes, but rendered %s.",
"56": "Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.",
"57": "Missing markup.",
"58": "Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().",
"59": "%s is a void element tag and must not have `children` or use `props.dangerouslySetInnerHTML`.",
"60": "Can only set one of `children` or `props.dangerouslySetInnerHTML`.",
"61": "`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://react.dev/link/dangerously-set-inner-html for more information.",
"62": "The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.",
"63": "Must be mounted to trap events",
"64": "Requires node to be rendered.",
"65": "Invalid tag: %s",
"66": "<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.",
"67": "Missing closing comment for text component %s",
"68": "Expected devtool events to fire for the child before its parent includes it in onSetChildren().",
"69": "Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().",
"70": "Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().",
"71": "Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().",
"72": "Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).",
"73": "ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.",
"74": "ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.",
"75": "ReactClass: You're attempting to use a component class or function as a mixin. Instead, just use a regular object.",
"76": "ReactClass: You're attempting to use a component as a mixin. Instead, just use a regular object.",
"77": "ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.",
"78": "ReactClass: You are attempting to define a reserved property, `%s`, that shouldn't be on the \"statics\" key. Define it as an instance property instead; it will still be accessible on the constructor.",
"79": "ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.",
"80": "mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.",
"81": "mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.",
"82": "%s.getInitialState(): must return an object or null",
"83": "Class specification must implement a `render` method.",
"84": "%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.",
"85": "takes an object of state variables to update or a function which returns an object of state variables.",
"86": "SimpleEventPlugin: Unhandled event type, `%s`.",
"87": "Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don't want to use valueLink and vice versa.",
"88": "Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don't want to use valueLink.",
"89": "Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don't want to use checkedLink",
"90": "ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.",
"91": "`dangerouslySetInnerHTML` does not make sense on <textarea>.",
"92": "If you supply `defaultValue` on a <textarea>, do not pass children.",
"93": "<textarea> can only have at most one child.",
"94": "Expected %s listener to be a function, instead got type %s",
"95": "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.",
"96": "EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.",
"97": "EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.",
"98": "EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.",
"99": "EventPluginRegistry: More than one plugin attempted to publish the same event name, `%s`.",
"100": "EventPluginRegistry: More than one plugin attempted to publish the same registration name, `%s`.",
"101": "EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.",
"102": "EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.",
"103": "Invalid `event`.",
"104": "ReactCompositeComponent: injectEnvironment() can only be called once.",
"105": "A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.",
"106": "%s.state: must be set to an object or null",
"107": "%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().",
"108": "%s.getChildContext(): key \"%s\" is not defined in childContextTypes.",
"109": "%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.",
"110": "Stateless function components cannot have refs.",
"111": "There is no registered component for the tag %s",
"112": "getNextDescendantID(%s, %s): Received an invalid React DOM ID.",
"113": "React has made an invalid assumption about the DOM hierarchy. Expected `%s` to be an ancestor of `%s`.",
"114": "getFirstCommonAncestorID(%s, %s): Expected a valid React DOM ID: %s",
"115": "Cannot traverse from and to the same ID, `%s`.",
"116": "traverseParentPath(%s, %s, ...): Cannot traverse from two IDs that do not have a parent path.",
"117": "traverseParentPath(%s, %s, ...): Detected an infinite loop while traversing the React DOM ID tree. This may be due to malformed IDs: %s",
"118": "updateTextContent called on non-empty component.",
"119": "Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://react.dev/link/refs-must-have-owner).",
"120": "Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://react.dev/link/refs-must-have-owner).",
"121": "performUpdateIfNecessary: Unexpected batch number (current %s, pending %s)",
"122": "%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.",
"123": "ReactUpdates: must inject a reconcile transaction class and batching strategy",
"124": "Expected flush transaction's stored dirty-components length (%s) to match dirty-components array length (%s).",
"125": "ReactUpdates.asap: Can't enqueue an asap callback in a context where updates are not being batched.",
"126": "ReactUpdates: must provide a reconcile transaction class",
"127": "ReactUpdates: must provide a batching strategy",
"128": "ReactUpdates: must provide a batchedUpdates() function",
"129": "ReactUpdates: must provide an isBatchingUpdates boolean attribute",
"130": "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",
"131": "Encountered invalid React node of type %s",
"132": "Ended a touch event which was not counted in trackedTouchCount.",
"133": "Touch object is missing identifier",
"134": "Touch data should have been recorded on start",
"135": "Cannot find single active touch",
"136": "Attempted to update component `%s` that has already been unmounted (or failed to mount).",
"137": "%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.",
"138": "Touch object is missing identifier.",
"139": "ReactTestRenderer: .update() can't be called after unmount.",
"140": "Expected hook events to fire for the child before its parent includes it in onSetChildren().",
"141": "Expected onSetChildren() to fire for a container child before its parent includes it in onSetChildren().",
"142": "Expected onBeforeMountComponent() parent and onSetChildren() to be consistent (%s has parents %s and %s).",
"143": "React.Children.only expected to receive a single React element child.",
"144": "Item must have been set",
"145": "hostContainerInfo should be populated before getPublicInstance is called.",
"146": "React Component in warnForMissingKey should have a _store. This error is likely caused by a bug in React. Please file an issue.",
"147": "Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.",
"148": "Expected ref to be a function or a string.",
"149": "Element ref was specified as a string (%s) but no owner was set. You may have multiple copies of React loaded. (details: https://react.dev/link/refs-must-have-owner).",
"150": "An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.",
"151": "An iterable object provided no iterator.",
"152": "Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.",
"153": "Resuming work not yet implemented.",
"154": "We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue.",
"155": "An indeterminate component should never have mounted. This error is likely caused by a bug in React. Please file an issue.",
"156": "Unknown unit of work tag (%s). This error is likely caused by a bug in React. Please file an issue.",
"157": "Invalid type of work. This error is likely caused by a bug in React. Please file an issue.",
"158": "There must be pending props for an initial mount. This error is likely caused by a bug in React. Please file an issue.",
"159": "There should always be pending or memoized props. This error is likely caused by a bug in React. Please file an issue.",
"160": "Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.",
"161": "Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue.",
"162": "This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue.",
"163": "This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.",
"164": "A coroutine cannot have host component children.",
"165": "Should be resolved by now. This error is likely caused by a bug in React. Please file an issue.",
"166": "We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.",
"167": "An indeterminate component should have become determinate before completing. This error is likely caused by a bug in React. Please file an issue.",
"168": "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue.",
"169": "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue.",
"170": "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.",
"171": "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue.",
"172": "The custom dialog was already injected.",
"173": "Injected showDialog() must be a function.",
"174": "Expected host context to exist. This error is likely caused by a bug in React. Please file an issue.",
"175": "Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.",
"176": "Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.",
"177": "Cannot commit the same tree as before. This error is likely caused by a bug in React. Please file an issue.",
"178": "Should have next effect. This error is likely caused by a bug in React. Please file an issue.",
"179": "Should have a pending commit. This error is likely caused by a bug in React. Please file an issue.",
"180": "Commit phase errors should be scheduled to recover with task priority. This error is likely caused by a bug in React. Please file an issue.",
2020-06-15 19:59:44 -04:00
"181": "Switch statement should be exhaustive. This error is likely caused by a bug in React. Please file an issue.",
"182": "performWork was called recursively. This error is likely caused by a bug in React. Please file an issue.",
"183": "Should have found an error boundary. This error is likely caused by a bug in React. Please file an issue.",
"184": "No error for given unit of work. This error is likely caused by a bug in React. Please file an issue.",
"185": "Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.",
"186": "Task updates can only be scheduled as a nested update or inside batchedUpdates.",
"187": "flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.",
"188": "Unable to find node on an unmounted component.",
"189": "Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue.",
"190": "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue.",
"191": "Invalid argument passed as callback. Expected a function. Instead received: %s",
"192": "React depends on requestAnimationFrame. Make sure that you load a polyfill in older browsers.",
"193": "The server renderer does not implement support for array children yet.",
"194": "Fiber needs to be injected to handle a fiber target for controlled events. This error is likely caused by a bug in React. Please file an issue.",
"195": "The internal instance must be a React host component. This error is likely caused by a bug in React. Please file an issue.",
"196": "Missing injection for fiber getContextForSubtree",
"197": "Injected invokeGuardedCallback() must be a function.",
"198": "clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.",
"199": "Fiber owners should not show up in Stack stack traces.",
"200": "Target container is not a DOM element.",
"201": "ReactDOM.render(): Invalid component element. Instead of passing a string like 'div', pass React.createElement('div') or <div />.",
"202": "ReactDOM.render(): Invalid component element. Instead of passing a class like Foo, pass React.createElement(Foo) or <Foo />.",
"203": "ReactDOM.render(): Invalid component element. This may be caused by unintentionally loading two independent copies of React.",
"204": "ReactDOM.render(): Invalid component element.",
"205": "renderToNodeStream(): Invalid component element.",
"206": "renderToStaticNodeStream(): Invalid component element.",
"207": "ReactDOMServer.renderToNodeStream(): The streaming API is not available in the browser. Use ReactDOMServer.renderToString() instead.",
"208": "ReactDOMServer.renderToStaticNodeStream(): The streaming API is not available in the browser. Use ReactDOMServer.renderToStaticMarkup() instead.",
"209": "renderToString(): Invalid component element.",
"210": "renderToStaticMarkup(): Invalid component element.",
"211": "Missing injection for fiber findDOMNode",
"212": "Missing injection for stack findDOMNode",
"213": "Element appears to be neither ReactComponent nor DOMNode. Keys: %s",
"214": "toTree() does not yet know how to handle nodes with tag=%s",
"215": "something went wrong",
"216": "Text children should already be flattened.",
"217": "ReactART does not support the type \"%s\"",
"218": "ReactART: Can not insert node before itself",
"219": "getInspectorDataForViewTag() is not available in production",
"220": "Container does not support insertBefore operation",
"221": "Tried to register two views with the same name %s",
"222": "View config not found for name %s",
"224": "Can't read from currently-mounting component. This error is likely caused by a bug in React. Please file an issue.",
"225": "Unexpected object passed to ReactTestInstance constructor (tag: %s). This is probably a bug in React.",
"226": "Unsupported component type %s in test renderer. This is probably a bug in React.",
"227": "ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.",
"228": "TestUtils.Simulate expected a DOM node as the first argument but received a React element. Pass the DOM node you wish to simulate the event on instead. Note that TestUtils.Simulate will not work if you are using shallow rendering.",
"229": "TestUtils.Simulate expected a DOM node as the first argument but received a component instance. Pass the DOM node you wish to simulate the event on instead.",
"230": "_processChildContext is not available in React 16+. This likely means you have multiple copies of React and are attempting to nest a React 15 tree inside a React 16 tree using unstable_renderSubtreeIntoContainer, which isn't supported. Try to make sure you have only one copy of React (and ideally, switch to ReactDOM.unstable_createPortal).",
2017-09-14 13:37:26 +01:00
"231": "Expected `%s` listener to be a function, instead got a value of `%s` type.",
"232": "_processChildContext is not available in React 16+. This likely means you have multiple copies of React and are attempting to nest a React 15 tree inside a React 16 tree using unstable_renderSubtreeIntoContainer, which isn't supported. Try to make sure you have only one copy of React (and ideally, switch to ReactDOM.createPortal).",
2017-09-26 08:44:21 -07:00
"233": "Unsupported top level event type \"%s\" dispatched",
[CS] Persistent Updates (#11260) * Update build size * [CS] Clone container instead of new root concept The extra "root" concept is kind of unnecessary. Instead of having a mutable container even in the persistent mode, I'll instead make the container be immutable too and be cloned. Then the "commit" just becomes swapping the previous container for the new one. * Change the signature or persistence again We may need to clone without any updates, e.g. when the children are changed. Passing in the previous node is not enough to recycle since it won't have the up-to-date props and children. It's really only useful to for allocation pooling. * Implement persistent updates This forks the update path for host fibers. For mutation mode we mark them as having an effect. For persistence mode, we clone the stateNode with new props/children. Next I'll do HostRoot and HostPortal. * Refine protocol into a complete and commit phase finalizeContainerChildren will get called at the complete phase. replaceContainer will get called at commit. Also, drop the keepChildren flag. We'll never keep children as we'll never update a container if none of the children has changed. * Implement persistent updates of roots and portals These are both "containers". Normally we rely on placement/deletion effects to deal with insertions into the containers. In the persistent mode we need to clone the container and append all the changed children to it. I needed somewhere to store these new containers before they're committed so I added another field. * Commit persistent work at the end by swapping out the container * Unify cloneOrRecycle Originally I tried to make the recyclable instance nullable but Flow didn't like that and it's kind of sketchy since the instance type might not be nullable. However, the real difference which one we call is depending on whether they are equal. We can just offload that to the renderer. Most of them won't need to know about this at all since they'll always clone or just create new. The ones that do know now have to be careful to compare them so they don't reuse an existing instance but that's probably fine to simplify the implementation and API. * Add persistent noop renderer for testing * Add basic persistent tree test * Test bail out This adds a test for bailouts. This revealed a subtle bug. We don't set the return pointer when stepping into newly created fibers because there can only be one. However, since I'm reusing this mechanism for persistent updates, I'll need to set the return pointer because a bailed out tree won't have the right return pointer. * Test persistent text nodes Found another bug. * Add persistent portal test This creates a bit of an unfortunate feature testing in the unmount branch. That's because we want to trigger nested host deletions in portals in the mutation mode. * Don't consider container when determining portal identity Basically, we can't use the container to determine if we should keep identity and update an existing portal instead of recreate it. Because for persistent containers, there is no permanent identity. This makes it kind of strange to even use portals in this mode. It's probably more ideal to have another concept that has permanent identity rather than trying to swap out containers. * Clear portals when the portal is deleted When a portal gets deleted we need to create a new empty container and replace the current one with the empty one. * Add renderer mode flags for dead code elimination * Simplify ReactNoop fix * Add new type to the host config for persistent configs We need container to stay as the persistent identity of the root atom. So that we can refer to portals over time. Instead, I'll introduce a new type just to temporarily hold the children of a container until they're ready to be committed into the permanent container. Essentially, this is just a fancy array that is not an array so that the host can choose data structure/allocation for it. * Implement new hooks Now containers are singletons and instead their children swap. That way portals can use the container as part of their identity again. * Update build size and error codes * Address comment * Move new files to new location
2017-10-18 18:28:23 -07:00
"234": "Event cannot be both direct and bubbling: %s",
"235": "Persistent reconciler is disabled.",
"236": "Noop reconciler is disabled.",
"237": "Mutating reconciler is disabled.",
"238": "Task updates can only be scheduled as a nested update or inside batchedUpdates. This error is likely caused by a bug in React. Please file an issue.",
"239": "Measure not implemented yet",
"240": "Text components are not supported for now.",
"241": "Text components are not yet supported.",
"242": "%s: %s type `%s` is invalid; it must be a function, usually from the `prop-types` package, but received `%s`.",
"243": "renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.",
"244": "Should have a previous and last root. This error is likely caused by a bug in React. Please file an issue.",
"245": "performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.",
"246": "Should be working on a root. This error is likely caused by a bug in React. Please file an issue.",
"247": "A call cannot have host component children.",
"248": "Not implemented.",
"249": "ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `%s`.",
"250": "batch.render: Cannot render a batch that already committed.",
"251": "batch.commit: Cannot commit a batch multiple times.",
"252": "The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.",
"253": "work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method.",
"254": "Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a functional component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://react.dev/link/refs-must-have-owner for more information.",
"255": "Expected ReactFbErrorUtils.invokeGuardedCallback to be a function.",
"257": "Portals are not currently supported by the server renderer. Render them conditionally so that they only appear on the client render.",
"258": "Unknown element-like object type: %s. This is likely a bug in React. Please file an issue.",
"259": "The experimental Call and Return types are not currently supported by the server renderer.",
"260": "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.",
"261": "Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue.",
"262": "Expired work should have completed. This error is likely caused by a bug in React. Please file an issue.",
"263": "dispatch: Cannot dispatch during the render phase.",
"264": "An error logging effect should not have been scheduled if no errors were captured. This error is likely caused by a bug in React. Please file an issue.",
2019-05-28 11:34:18 -06:00
"265": "This unit of work tag cannot capture errors. This error is likely caused by a bug in React. Please file an issue.",
2018-04-16 16:23:12 +01:00
"266": "A subscription must return an unsubscribe function.",
"267": "The argument must be a React element, but you passed %s.",
2018-05-13 21:12:25 +01:00
"268": "Argument appears to not be a ReactComponent. Keys: %s",
2018-05-23 17:35:31 -07:00
"269": "Profiler must specify an \"id\" string and \"onRender\" function as props",
"270": "The current renderer does not support persistence. This error is likely caused by a bug in React. Please file an issue.",
"271": "Failed to replay rendering after an error. This is likely caused by a bug in React. Please file an issue with a reproducing case to help us find it.",
"273": "Nesting of <View> within <Text> is not currently supported.",
"274": "Text strings must be rendered within a <Text> component.",
2018-06-13 17:20:35 +01:00
"275": "The current renderer does not support mutation. This error is likely caused by a bug in React. Please file an issue.",
"276": "React depends on requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://react.dev/link/react-polyfills",
2018-09-06 09:34:27 -07:00
"277": "Context.unstable_read(): Context can only be read while React is rendering, e.g. inside the render method or getDerivedStateFromProps.",
"278": "unstable_createRoot(...): Target container is not a DOM element.",
"279": "Trying to release an event instance into a pool of a different type.",
"280": "setRestoreImplementation() needs to be called to handle a target for controlled events. This error is likely caused by a bug in React. Please file an issue.",
"281": "Finished root should have a work-in-progress. This error is likely caused by a bug in React. Please file an issue.",
"282": "If the root does not have an updateQueue, we should have already bailed out. This error is likely caused by a bug in React. Please file an issue.",
"283": "Element type is invalid. Received a promise that resolves to: %s. Promise elements must resolve to a class or function.",
"284": "Expected ref to be a function, an object returned by React.createRef(), or undefined/null.",
2018-09-06 09:34:27 -07:00
"285": "The root failed to unmount after an error. This is likely a bug in React. Please file an issue.",
2018-09-13 19:11:31 +01:00
"286": "%s(...): the first argument must be a React class instance. Instead received: %s.",
"287": "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracking` module with `schedule/tracking-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://react.dev/link/profiling",
"288": "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracing` module with `schedule/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://react.dev/link/profiling",
"289": "Function components cannot have refs.",
"290": "Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a function component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://react.dev/link/refs-must-have-owner for more information.",
"292": "The matcher `toHaveYielded` expects an instance of React Test Renderer.\n\nTry: expect(Scheduler).toHaveYielded(expectedYields)",
2018-10-23 16:29:35 -07:00
"293": "Context can only be read while React is rendering, e.g. inside the render method or getDerivedStateFromProps.",
"294": "ReactDOMServer does not yet support Suspense.",
"295": "ReactDOMServer does not yet support lazy-loaded components.",
2018-11-06 18:28:50 -08:00
"297": "The matcher `unstable_toHaveYielded` expects an instance of React Test Renderer.\n\nTry: expect(ReactTestRenderer).unstable_toHaveYielded(expectedYields)",
"298": "Hooks can only be called inside the body of a function component.",
"299": "Target container is not a DOM element.",
2018-11-06 18:28:50 -08:00
"300": "Rendered fewer hooks than expected. This may be caused by an accidental early return statement.",
2018-11-12 17:59:06 -08:00
"301": "Too many re-renders. React limits the number of renders to prevent an infinite loop.",
"302": "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at https://react.dev/link/profiling",
"303": "ReactDOMServer did not find an internal fallback frame for Suspense. This is a bug in React. Please file an issue.",
2018-11-12 17:59:06 -08:00
"304": "Maximum number of concurrent React renderers exceeded. This can happen if you are not properly destroying the Readable provided by React. Ensure that you call .destroy() on it if you no longer want to read from it, and did not read to the end. If you use .pipe() this should be automatic.",
2018-12-19 17:23:14 -08:00
"305": "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue.",
2019-02-06 08:04:00 +00:00
"306": "Element type is invalid. Received a promise that resolves to: %s. Lazy element type must resolve to a class or function.%s",
"307": "Hooks can only be called inside the body of a function component. (https://react.dev/link/invalid-hook-call)",
2019-02-06 08:04:00 +00:00
"308": "Context can only be read while React is rendering. In classes, you can read it in the render method or getDerivedStateFromProps. In function components, you can read it directly in the function body, but not inside Hooks like useReducer() or useMemo().",
"309": "Function components cannot have string refs. We recommend using useRef() instead. Learn more about using refs safely here: https://react.dev/link/strict-mode-string-ref",
2019-02-06 08:04:00 +00:00
"310": "Rendered more hooks than during the previous render.",
"311": "Should have a queue. You are likely calling Hooks conditionally, which is not allowed. (https://react.dev/link/invalid-hook-call)",
2019-02-14 19:12:42 +00:00
"312": "Rendered more hooks than during the previous render",
"313": "Unknown priority level. This error is likely caused by a bug in React. Please file an issue.",
"314": "Pinged unknown suspense boundary type. This is probably a bug in React.",
"315": "Suspense boundaries are never on the root. This is probably a bug in React.",
"316": "Expected skipPastDehydratedSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.",
"317": "Expected to have a hydrated suspense instance. This error is likely caused by a bug in React. Please file an issue.",
"318": "A dehydrated suspense component was completed without a hydrated node. This is probably a bug in React.",
"319": "A dehydrated suspense boundary must commit before trying to render. This is probably a bug in React.",
2019-03-22 16:41:58 +00:00
"320": "Expected ReactFiberErrorDialog.showErrorDialog to be a function.",
"321": "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.",
2019-05-29 11:29:04 -07:00
"322": "forwardRef requires a render function but was given %s.",
"323": "React has blocked a javascript: URL as a security precaution.",
2019-05-29 11:29:04 -07:00
"326": "Expected a valid priority level",
"327": "Should not already be working.",
"328": "Should have a work-in-progress.",
"329": "Unknown root exit status.",
"330": "Should be working on an effect.",
"331": "Cannot flush passive effects while already rendering.",
"332": "Unknown priority level.",
"333": "This should have a parent host component initialized. This error is likely caused by a bug in React. Please file an issue.",
"334": "Accumulated items must not be null or undefined.",
"335": "ReactDOMServer does not yet support the event API.",
"338": "ReactDOMServer does not yet support the fundamental API.",
Refactor Partial Hydration (#16346) * Move dehydrated to be child of regular SuspenseComponent We now store the comment node on SuspenseState instead and that indicates that this SuspenseComponent is still dehydrated. We also store a child but that is only used to represent the DOM node for deletions and getNextHostSibling. * Move logic from DehydratedSuspenseComponent to SuspenseComponent Forked based on SuspenseState.dehydrated instead. * Retry logic for dehydrated boundary We can now simplify the logic for retrying dehydrated boundaries without hydrating. This is becomes simply a reconciliation against the dehydrated fragment which gets deleted, and the new children gets inserted. * Remove dehydrated from throw Instead we use the regular Suspense path. To save code, we attach retry listeners in the commit phase even though technically we don't have to. * Pop to nearest Suspense I think this is right...? * Popping hydration state should skip past the dehydrated instance * Split mount from update and special case suspended second pass The DidCapture flag isn't used consistently in the same way. We need further refactor for this. * Reorganize update path If we remove the dehydration status in the first pass and then do a second pass because we suspended, then we need to continue as if it didn't previously suspend. Since there is no fragment child etc. However, we must readd the deletion. * Schedule context work on the boundary and not the child * Warn for Suspense hydration in legacy mode It does a two pass render that client renders the content. * Rename DehydratedSuspenseComponent -> DehydratedFragment This now doesn't represent a suspense boundary itself. Its parent does. This Fiber represents the fragment around the dehydrated content. * Refactor returns Avoids the temporary mutable variables. I kept losing track of them. * Add a comment explaining the type. Placing it in the type since that's the central point as opposed to spread out.
2019-08-12 15:58:38 -07:00
"340": "Threw in newly mounted dehydrated component. This is likely a bug in React. Please file an issue.",
"341": "We just came from a parent so we must have had a parent. This is a bug in React.",
"342": "A React component suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.",
"343": "ReactDOMServer does not yet support scope components.",
[suspense][error handling] Inline renderRoot and fix error handling bug (#16801) * Outline push/pop logic in `renderRoot` I want to get rid of the the `isSync` argument to `renderRoot`, and instead use separate functions for concurrent and synchronous render. As a first step, this extracts the push/pop logic that happens before and after the render phase into helper functions. * Extract `catch` block into helper function Similar to previous commit. Extract error handling logic into a separate function so it can be reused. * Fork `renderRoot` for sync and concurrent Removes `isSync` argument in favor of separate functions. * Extra "root completion" logic to separate function Moving this out to avoid an accidental early return, which would bypass the call to `ensureRootIsScheduled` and freeze the UI. * Inline `renderRoot` Inlines `renderRoot` into `performConcurrentWorkOnRoot` and `performSyncWorkOnRoot`. This lets me remove the `isSync` argument and also get rid of a redundant try-catch wrapper. * [suspense][error handling] Add failing unit test Covers an edge case where an error is thrown inside the complete phase of a component that is in the return path of a component that suspends. The second error should also be handled (i.e. able to be captured by an error boundary. The test is currently failing because there's a call to `completeUnitOfWork` inside the main render phase `catch` block. That call is not itself wrapped in try-catch, so anything that throws is treated as a fatal/unhandled error. I believe this bug is only observable if something in the host config throws; and, only in legacy mode, because in concurrent/batched mode, `completeUnitOfWork` on fiber that throws follows the "unwind" path only, not the "complete" path, and the "unwind" path does not call any host config methods. * [scheduler][profiler] Start time of delayed tasks Fixes a bug in the Scheduler profiler where the start time of a delayed tasks is always 0. * Remove ad hoc `throw` Fatal errors (errors that are not captured by an error boundary) are currently rethrown from directly inside the render phase's `catch` block. This is a refactor hazard because the code in this branch has to mirror the code that happens at the end of the function, when exiting the render phase in the normal case. This commit moves the throw to the end, using a new root exit status. * Handle errors that occur on unwind
2019-09-23 11:23:28 -07:00
"344": "Expected prepareToHydrateHostSuspenseInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.",
"345": "Root did not complete. This is a bug in React.",
"348": "ensureListeningTo(): received a container that was not an element node. This is likely a bug in React.",
"349": "Expected a work-in-progress root. This is a bug in React. Please file an issue.",
useMutableSource: Use StrictMode double render to detect render phase mutation (#20698) * Concurrent Mode test for uMS render mutation Same test as the one added in #20665, but for Concurrent Mode. * Use double render to detect render phase mutation PR #20665 added a mechanism to detect when a `useMutableSource` source is mutated during the render phase. It relies on the fact that we double invoke components that error during development using `invokeGuardedCallback`. If the version in the double render doesn't match the first, that indicates there must have been a mutation during render. At first I thought it worked by detecting inside the *other* double render, the one we do for Strict Mode. It turns out that while it does warn then, the warning is suppressed, because we suppress all console methods that occur during the Strict Mode double render. So it's really the `invokeGuardedCallback` one that makes it work. Anyway, let's set that aside that issue for a second. I realized during review that errors that occur during the Strict Mode double render reveal a useful property: A pure component will never throw during the double render, because if it were pure, it would have also thrown during the first render... in which case it wouldn't have double rendered! This is true of all such errors, not just the one thrown by `useMutableSource`. Given this, we can simplify the `useMutableSource` mutation detection mechanism. Instead of tracking and comparing the source's version, we can instead check if we're inside a double render when the error is thrown. To get around the console suppression issue, I changed the warning to an error. It errors regardless, in both dev and prod, so it doesn't have semantic implications. However, because of the paradox I described above, we arguably _shouldn't_ throw an error in development, since we know that error won't happen in production, because prod doesn't double render. (It's still a tearing bug, but that doesn't mean the component will actually throw.) I considered that, but that requires a larger conversation about how to handle errors that we know are only possible in development. I think we should probably be suppressing *all* errors (with a warning) that occur during a double render.
2021-02-01 14:11:51 -06:00
"350": "Cannot read from mutable source during the current render without tearing. This may be a bug in React. Please file an issue.",
"351": "Unsupported Server Component type: %s",
"352": "React Lazy Components are not yet supported on the server.",
"353": "A server block should never encode any other slots. This is a bug in React.",
"354": "getInspectorDataForViewAtPoint() is not available in production.",
"355": "The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly. (TODO: This feature was never released so we should be able to remove this error from the map.)",
"356": "Could not read the cache.",
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
"357": "The current renderer does not support React Scopes. This error is likely caused by a bug in React. Please file an issue.",
"358": "Invalid update priority: %s. This is a bug in React.",
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
"360": "Invalid lane: %s. This is a bug in React.",
"361": "The current renderer does not support test selectors. This error is likely caused by a bug in React. Please file an issue.",
"362": "Could not find React container within specified host subtree.",
"363": "Test selector API is not supported by this renderer.",
"364": "Invalid host root specified. Should be either a React container or a node with a testname attribute.",
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-09-30 15:01:28 -04:00
"365": "Invalid selector type specified.",
"366": "ReactDOM.createEventHandle: setListener called on an target that did not have a corresponding root. This is likely a bug in React.",
"367": "ReactDOM.createEventHandle: setListener called on an element target that is not managed by React. Ensure React rendered the DOM element.",
"368": "ReactDOM.createEventHandle: setListener called on an invalid target. Provide a valid EventTarget or an element managed by React.",
"369": "ReactDOM.createEventHandle: setter called on an invalid target. Provide a valid EventTarget or an element managed by React.",
"370": "ReactDOM.createEventHandle: setter called with an invalid callback. The callback must be a function.",
"371": "Text string must be rendered within a <Text> component.\n\nText: %s",
"372": "Cannot call unstable_createEventHandle with \"%s\", as it is not an event known to React.",
"373": "This Hook is not supported in Server Components.",
"374": "Event handlers cannot be passed to Client Component props.%s\nIf you need interactivity, consider converting part of this to a Client Component.",
"375": "Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with \"use server\". Or maybe you meant to call this function rather than return it.%s",
"376": "Only global symbols received from Symbol.for(...) can be passed to Client Components. The symbol Symbol.for(%s) cannot be found among global symbols.%s",
"377": "BigInt (%s) is not yet supported in Client Component props.%s",
"378": "Type %s is not supported in Client Component props.%s",
"379": "Refs cannot be used in Server Components, nor passed to Client Components.",
"380": "Reading the cache is only supported while rendering.",
"381": "This feature is not supported by ReactSuspenseTestUtils.",
"382": "This query has received more parameters than the last time the same query was used. Always pass the exact number of parameters that the query needs.",
"383": "This query has received fewer parameters than the last time the same query was used. Always pass the exact number of parameters that the query needs.",
"384": "Refreshing the cache is not supported in Server Components.",
Add `supportsMicrotasks` to the host config (#20809) * Add `supportsMicrotasks` to the host config Only certain renderers support scheduling a microtask, so we need a renderer specific flag that we can toggle. That way it's off for some renderers and on for others. I copied the approach we use for the other optional parts of the host config, like persistent mode and test selectors. Why isn't the feature flag sufficient? The feature flag modules, confusingly, are not renderer-specific, at least when running the our tests against the source files. They are meant to correspond to a release channel, not a renderer, but we got confused at some point and haven't cleaned it up. For example, when we run `yarn test`, Jest loads the flags from the default `ReactFeatureFlags.js` module, even when we import the React Native renderer — but in the actual builds, we load a different feature flag module, `ReactFeatureFlags.native-oss.js.` There's no way in our current Jest load a different host config for each renderer, because they all just import the same module. We should solve this by creating separate Jest project for each renderer, so that the flags loaded when running against source are the same ones that we use in the compiled bundles. The feature flag (`enableDiscreteMicrotasks`) still exists — it's used to set the React DOM host config's `supportsMicrotasks` flag to `true`. (Same for React Noop) The important part is that turning on the feature flag does *not* affect the other renderers, like React Native. The host config will likely outlive the feature flag, too, since the feature flag only exists so we can gradually roll it out and measure the impact in production; once we do, we'll remove it. Whereas the host config flag may continue to be used to disable the discrete microtask behavior for RN, because RN will likely use a native (non-JavaScript) API to schedule its tasks. * Add `supportsMicrotask` to react-reconciler README
2021-02-12 15:13:49 -06:00
"385": "A mutable source was mutated while the %s component was rendering. This is not supported. Move any mutations into event handlers or effects.",
[Experiment] Lazily propagate context changes (#20890) * Move context comparison to consumer In the lazy context implementation, not all context changes are propagated from the provider, so we can't rely on the propagation alone to mark the consumer as dirty. The consumer needs to compare to the previous value, like we do for state and context. I added a `memoizedValue` field to the context dependency type. Then in the consumer, we iterate over the current dependencies to see if something changed. We only do this iteration after props and state has already bailed out, so it's a relatively uncommon path, except at the root of a changed subtree. Alternatively, we could move these comparisons into `readContext`, but that's a much hotter path, so I think this is an appropriate trade off. * [Experiment] Lazily propagate context changes When a context provider changes, we scan the tree for matching consumers and mark them as dirty so that we know they have pending work. This prevents us from bailing out if, say, an intermediate wrapper is memoized. Currently, we propagate these changes eagerly, at the provider. However, in many cases, we would have ended up visiting the consumer nodes anyway, as part of the normal render traversal, because there's no memoized node in between that bails out. We can save CPU cycles by propagating changes only when we hit a memoized component — so, instead of propagating eagerly at the provider, we propagate lazily if or when something bails out. Most of our bailout logic is centralized in `bailoutOnAlreadyFinishedWork`, so this ended up being not that difficult to implement correctly. There are some exceptions: Suspense and Offscreen. Those are special because they sometimes defer the rendering of their children to a completely separate render cycle. In those cases, we must take extra care to propagate *all* the context changes, not just the first one. I'm pleasantly surprised at how little I needed to change in this initial implementation. I was worried I'd have to use the reconciler fork, but I ended up being able to wrap all my changes in a regular feature flag. So, we could run an experiment in parallel to our other ones. I do consider this a risky rollout overall because of the potential for subtle semantic deviations. However, the model is simple enough that I don't expect us to have trouble fixing regressions if or when they arise during internal dogfooding. --- This is largely based on [RFC#118](https://github.com/reactjs/rfcs/pull/118), by @gnoff. I did deviate in some of the implementation details, though. The main one is how I chose to track context changes. Instead of storing a dirty flag on the stack, I added a `memoizedValue` field to the context dependency object. Then, to check if something has changed, the consumer compares the new context value to the old (memoized) one. This is necessary because of Suspense and Offscreen — those components defer work from one render into a later one. When the subtree continues rendering, the stack from the previous render is no longer available. But the memoized values on the dependencies list are. This requires a bit more work when a consumer bails out, but nothing considerable, and there are ways we could optimize it even further. Conceptually, this model is really appealing, since it matches how our other features "reactively" detect changes — `useMemo`, `useEffect`, `getDerivedStateFromProps`, the built-in cache, and so on. I also intentionally dropped support for `unstable_calculateChangedBits`. We're planning to remove this API anyway before the next major release, in favor of context selectors. It's an unstable feature that we never advertised; I don't think it's seen much adoption. Co-Authored-By: Josh Story <jcs.gnoff@gmail.com> * Propagate all contexts in single pass Instead of propagating the tree once per changed context, we can check all the contexts in a single propagation. This inverts the two loops so that the faster loop (O(numberOfContexts)) is inside the more expensive loop (O(numberOfFibers * avgContextDepsPerFiber)). This adds a bit of overhead to the case where only a single context changes because you have to unwrap the context from the array. I'm also unsure if this will hurt cache locality. Co-Authored-By: Josh Story <jcs.gnoff@gmail.com> * Stop propagating at nearest dependency match Because we now propagate all context providers in a single traversal, we can defer context propagation to a subtree without losing information about which context providers we're deferring — it's all of them. Theoretically, this is a big optimization because it means we'll never propagate to any tree that has work scheduled on it, nor will we ever propagate the same tree twice. There's an awkward case related to bailing out of the siblings of a context consumer. Because those siblings don't bail out until after they've already entered the begin phase, we have to do extra work to make sure they don't unecessarily propagate context again. We could avoid this by adding an earlier bailout for sibling nodes, something we've discussed in the past. We should consider this during the next refactor of the fiber tree structure. Co-Authored-By: Josh Story <jcs.gnoff@gmail.com> * Mark trees that need propagation in readContext Instead of storing matched context consumers in a Set, we can mark when a consumer receives an update inside `readContext`. I hesistated to put anything in this function because it's such a hot path, but so are bail outs. Fortunately, we only need to set this flag once, the first time a context is read. So I think it's a reasonable trade off. In exchange, propagation is faster because we no longer need to accumulate a Set of matched consumers, and fiber bailouts are faster because we don't need to consult that Set. And the code is simpler. Co-authored-by: Josh Story <jcs.gnoff@gmail.com>
2021-03-07 00:56:53 -06:00
"386": "The current renderer does not support microtasks. This error is likely caused by a bug in React. Please file an issue.",
"387": "Should have a current fiber. This is a bug in React.",
"388": "Expected to find a bailed out fiber. This is a bug in React.",
"389": "There can only be one root segment. This is a bug in React.",
"390": "Aborted, errored or already flushed boundaries should not be flushed again. This is a bug in React.",
"391": "A previously unvisited boundary must have exactly one root segment. This is a bug in React.",
"392": "A root segment ID must have been assigned by now. This is a bug in React.",
"393": "Cache cannot be refreshed during server rendering.",
"394": "startTransition cannot be called during server rendering.",
"395": "An ID must have been assigned before we can complete the boundary.",
"396": "More boundaries or placeholders than we expected to ever emit.",
"397": "Unknown insertion mode. This is a bug in React.",
"398": "`dangerouslySetInnerHTML` does not work on <option>.",
"399": "%s is a self-closing tag and must neither have `children` nor use `dangerouslySetInnerHTML`.",
"400": "menuitems cannot have `children` nor `dangerouslySetInnerHTML`.",
"401": "The stacks must reach the root at the same time. This is a bug in React.",
"402": "The depth must equal at least at zero before reaching the root. This is a bug in React.",
"403": "Tried to pop a Context at the root of the app. This is a bug in React.",
"404": "Invalid hook call. Hooks can only be called inside of the body of a function component.",
"405": "hydrateRoot(...): Target container is not a DOM element.",
"406": "act(...) is not supported in production builds of React.",
"407": "Missing getServerSnapshot, which is required for server-rendered content. Will revert to client rendering.",
"408": "Missing getServerSnapshot, which is required for server-rendered content.",
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-09-30 15:01:28 -04:00
"409": "Cannot update an unmounted root.",
"411": "%s suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.",
"412": "Connection closed.",
"413": "Expected finished root and lanes to be set. This is a bug in React.",
"414": "Did not expect this call in production. This is a bug in React. Please file an issue.",
"415": "Error parsing the data. It's probably an error code or network corruption.",
"416": "This environment don't support binary chunks.",
"417": "React currently only supports piping to one writable stream.",
"418": "Hydration failed because the server rendered %s didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:\n\n- A server/client branch `if (typeof window !== 'undefined')`.\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n- Date formatting in a user's locale which doesn't match the server.\n- External changing data without sending a snapshot of it along with the HTML.\n- Invalid HTML tag nesting.\n\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\nhttps://react.dev/link/hydration-mismatch%s",
"419": "The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.",
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 07:55:32 -05:00
"420": "ServerContext: %s already defined",
"421": "This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition.",
Use a Wrapper Error for onRecoverableError with a "cause" Field for the real Error (#28736) We basically have four kinds of recoverable errors: - Hydration mismatches. - Server errored but client didn't. - Hydration render errored but client render didn't (in Root or Suspense boundary). - Concurrent render errored but synchronous render didn't. For the first three we log an additional error that the root or Suspense boundary didn't error. This provides some context about what happened. However, the problem is that for hydration mismatches that's unnecessary extra context that is confusing. We also don't log any additional context for concurrent render errors that could recover. This used to be the only recoverable error so it didn't need extra context but now we need to distinguish them. When we log these to `reportError` it's confusing to just see the error because you didn't see anything error on the page. It's also hard to group them together as one. In this PR, I remove the unnecessary context for hydration mismatches. For hydration and concurrent errors, I now wrap them in an error that describes that what happened but then use the new `cause` field to link the original error so we can keep that as the cause. The error that happened was that hydration client rendered or you deopted to sync render, the cause of that error is some other error. For server errors, we control the Error object so I already had added some context to that error object's message. Since we hide the message in prod, it's nice not to have the raw message in DEV neither. We could potentially split these into two errors for parity though.
2024-04-03 21:53:07 -04:00
"422": "There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.",
"423": "There was an error while hydrating but React was able to recover by instead client rendering the entire root.",
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 07:55:32 -05:00
"424": "This root received an early update, before anything was able hydrate. Switched the entire root to client rendering.",
"425": "Text content does not match server-rendered HTML.",
"426": "A component suspended while responding to synchronous input. This will cause the UI to be replaced with a loading indicator. To fix, updates that suspend should be wrapped with startTransition.",
"427": "useServerContext expects a context created with React.createServerContext",
"428": "useServerContext is only supported while rendering.",
"429": "ServerContext: %s already defined",
"430": "ServerContext can only have a value prop and children. Found: %s",
"431": "React elements are not allowed in ServerContext",
"432": "The render was aborted by the server without a reason.",
"433": "useId can only be used while React is rendering",
"434": "`dangerouslySetInnerHTML` does not make sense on <title>.",
"435": "Unexpected Suspense handler tag (%s). This is a bug in React.",
"436": "Stylesheet resources need a unique representation in the DOM while hydrating and more than one matching DOM Node was found. To fix, ensure you are only rendering one stylesheet link with an href attribute of \"%s\".",
experimental_use(promise) (#25084) * Internal `act`: Unwrapping resolved promises This update our internal implementation of `act` to support React's new behavior for unwrapping promises. Like we did with Scheduler, when something suspends, it will yield to the main thread so the microtasks can run, then continue in a new task. I need to implement the same behavior in the public version of `act`, but there are some additional considerations so I'll do that in a separate commit. * Move throwException to after work loop resumes throwException is the function that finds the nearest boundary and schedules it for a second render pass. We should only call it right before we unwind the stack — not if we receive an immediate ping and render the fiber again. This was an oversight in 8ef3a7c that I didn't notice because it happens to mostly work, anyway. What made me notice the mistake is that throwException also marks the entire render phase as suspended (RootDidSuspend or RootDidSuspendWithDelay), which is only supposed to be happen if we show a fallback. One consequence was that, in the RootDidSuspendWithDelay case, the entire commit phase was blocked, because that's the exit status we use to block a bad fallback from appearing. * Use expando to check whether promise has resolved Add a `status` expando to a thrown thenable to track when its value has resolved. In a later step, we'll also use `value` and `reason` expandos to track the resolved value. This is not part of the official JavaScript spec — think of it as an extension of the Promise API, or a custom interface that is a superset of Thenable. However, it's inspired by the terminology used by `Promise.allSettled`. The intent is that this will be a public API — Suspense implementations can set these expandos to allow React to unwrap the value synchronously without waiting a microtask. * Scaffolding for `experimental_use` hook Sets up a new experimental hook behind a feature flag, but does not implement it yet. * use(promise) Adds experimental support to Fiber for unwrapping the value of a promise inside a component. It is not yet implemented for Server Components, but that is planned. If promise has already resolved, the value can be unwrapped "immediately" without showing a fallback. The trick we use to implement this is to yield to the main thread (literally suspending the work loop), wait for the microtask queue to drain, then check if the promise resolved in the meantime. If so, we can resume the last attempted fiber without unwinding the stack. This functionality was implemented in previous commits. Another feature is that the promises do not need to be cached between attempts. Because we assume idempotent execution of components, React will track the promises that were used during the previous attempt and reuse the result. You shouldn't rely on this property, but during initial render it mostly just works. Updates are trickier, though, because if you used an uncached promise, we have no way of knowing whether the underlying data has changed, so we have to unwrap the promise every time. It will still work, but it's inefficient and can lead to unnecessary fallbacks if it happens during a discrete update. When we implement this for Server Components, this will be less of an issue because there are no updates in that environment. However, it's still better for performance to cache data requests, so the same principles largely apply. The intention is that this will eventually be the only supported way to suspend on arbitrary promises. Throwing a promise directly will be deprecated.
2022-08-25 14:12:07 -04:00
"437": "the \"precedence\" prop for links to stylesheets expects to receive a string but received something of type \"%s\" instead.",
"438": "An unsupported type was passed to use(): %s",
"439": "We didn't expect to see a forward reference. This is a bug in the React Server.",
"440": "A function wrapped in useEffectEvent can't be called during rendering.",
"441": "An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.",
"442": "The current renderer does not support Resources. This error is likely caused by a bug in React. Please file an issue.",
"443": "acquireResource encountered a resource type it did not expect: \"%s\". this is a bug in React.",
Model Float on Hoistables semantics (#26106) ## Hoistables In the original implementation of Float, all hoisted elements were treated like Resources. They had deduplication semantics and hydrated based on a key. This made certain kinds of hoists very challenging such as sequences of meta tags for `og:image:...` metadata. The reason is each tag along is not dedupable based on only it's intrinsic properties. two identical tags may need to be included and hoisted together with preceding meta tags that describe a semantic object with a linear set of html nodes. It was clear that the concept of Browser Resources (stylesheets / scripts / preloads) did not extend universally to all hositable tags (title, meta, other links, etc...) Additionally while Resources benefit from deduping they suffer an inability to update because while we may have multiple rendered elements that refer to a single Resource it isn't unambiguous which element owns the props on the underlying resource. We could try merging props, but that is still really hard to reason about for authors. Instead we restrict Resource semantics to freezing the props at the time the Resource is first constructed and warn if you attempt to render the same Resource with different props via another rendered element or by updating an existing element for that Resource. This lack of updating restriction is however way more extreme than necessary for instances that get hoisted but otherwise do not dedupe; where there is a well defined DOM instance for each rendered element. We should be able to update props on these instances. Hoistable is a generalization of what Float tries to model for hoisting. Instead of assuming every hoistable element is a Resource we now have two distinct categories, hoistable elements and hoistable resources. As one might guess the former has semantics that match regular Host Components except the placement of the node is usually in the <head>. The latter continues to behave how the original implementation of HostResource behaved with the first iteration of Float ### Hoistable Element On the server hoistable elements render just like regular tags except the output is stored in special queues that can be emitted in the stream earlier than they otherwise would be if rendered in place. This also allow for instance the ability to render a hoistable before even rendering the <html> tag because the queues for hoistable elements won't flush until after we have flushed the preamble (`<DOCTYPE html><html><head>`). On the client, hoistable elements largely operate like HostComponents. The most notable difference is in the hydration strategy. If we are hydrating and encounter a hoistable element we will look for all tags in the document that could potentially be a match and we check whether the attributes match the props for this particular instance. We also do this in the commit phase rather than the render phase. The reason hydration can be done for HostComponents in render is the instance will be removed from the document if hydration fails so mutating it in render is safe. For hoistables the nodes are not in a hydration boundary (Root or SuspenseBoundary at time of writing) and thus if hydration fails and we may have an instance marked as bound to some Fiber when that Fiber never commits. Moving the hydration matching to commit ensures we will always succeed in pairing the hoisted DOM instance with a Fiber that has committed. ### Hoistable Resource On the server and client the semantics of Resources are largely the same they just don't apply to title, meta, and most link tags anymore. Resources hoist and dedupe via an `href` key and are ref counted. In a future update we will add a garbage collector so we can clean up Resources that no longer have any references ## `<style>` support In earlier implementations there was no support for <style> tags. This PR adds support for treating `<style href="..." precedence="...">...</style>` as a Resource analagous to `<link rel="stylesheet" href="..." precedence="..." />` It may seem odd at first to require an href to get Resource semantics for a style tag. The rationale is that these are for inlining of actual external stylesheets as an optimization and for URI like scoping of inline styles for css-in-js libraries. The href indicates that the key space for `<style>` and `<link rel="stylesheet" />` Resources is shared. and the precedence is there to allow for interleaving of both kinds of Style resources. This is an advanced feature that we do not expect most app developers to use directly but will be quite handy for various styling libraries and for folks who want to inline as much as possible once Fizz supports this feature. ## refactor notes * HostResource Fiber type is renamed HostHoistable to reflect the generalization of the concept * The Resource object representation is modified to reduce hidden class checks and to use less memory overall * The thing that distinguishes a resource from an element is whether the Fiber has a memoizedState. If it does, it will use resource semantics, otherwise element semantics * The time complexity of matching hositable elements for hydration should be improved
2023-02-09 22:59:29 -08:00
"444": "getResource encountered a type it did not expect: \"%s\". this is a bug in React.",
"445": "\"currentResources\" was expected to exist. This is a bug in React.",
"446": "\"resourceRoot\" was expected to exist. This is a bug in React.",
"447": "While attempting to insert a Resource, React expected the Document to contain a head element but it was not found.",
"448": "createPortal was called on the server. Portals are not currently supported on the server. Update your program to conditionally call createPortal on the client only.",
"449": "flushSync was called on the server. This is likely caused by a function being called during render or in module scope that was intended to be called from an effect or event handler. Update your to not call flushSync no the server.",
"450": "The current renderer does not support Singletons. This error is likely caused by a bug in React. Please file an issue.",
"451": "resolveSingletonInstance was called with an element type that is not supported. This is a bug in React.",
"452": "React expected an <html> element (document.documentElement) to exist in the Document but one was not found. React never removes the documentElement for any Document it renders into so the cause is likely in some other script running on this page.",
"453": "React expected a <head> element (document.head) to exist in the Document but one was not found. React never removes the head for any Document it renders into so the cause is likely in some other script running on this page.",
"454": "React expected a <body> element (document.body) to exist in the Document but one was not found. React never removes the body for any Document it renders into so the cause is likely in some other script running on this page.",
"455": "This CacheSignal was requested outside React which means that it is immediately aborted.",
"456": "Calling Offscreen.detach before instance handle has been set.",
"457": "acquireHeadResource encountered a resource type it did not expect: \"%s\". This is a bug in React.",
"458": "Currently React only supports one RSC renderer at a time.",
"459": "Expected a suspended thenable. This is a bug in React. Please file an issue.",
"460": "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`.",
"461": "This is not a real error. It's an implementation detail of React's selective hydration feature. If this leaks into userspace, it's a bug in React. Please file an issue.",
"462": "Unexpected SuspendedReason. This is a bug in React.",
"463": "ReactDOMServer.renderToNodeStream(): The Node Stream API is not available in Bun. Use ReactDOMServer.renderToReadableStream() instead.",
"464": "ReactDOMServer.renderToStaticNodeStream(): The Node Stream API is not available in Bun. Use ReactDOMServer.renderToReadableStream() instead.",
"465": "enableFizzExternalRuntime without enableFloat is not supported. This should never appear in production, since it means you are using a misconfigured React bundle.",
"466": "Trying to call a function from \"use server\" but the callServer option was not implemented in your router runtime.",
[Float][Fiber] implement a faster hydration match for hoistable elements (#26154) This PR is now based on #26256 The original matching function for `hydrateHoistable` some challenging time complexity since we built up the list of matchable nodes for each link of that type and then had to check to exclusion. This new implementation aims to improve the complexity For hoisted title tags we match the first title if it is valid (not in SVG context and does not have `itemprop`, the two ways you opt out of hoisting when rendering titles). This path is much faster than others and we use it because valid Documents only have 1 title anyway and if we did have a mismatch the rendered title still ends up as the Document.title so there is no functional degradation for misses. For hoisted link and meta tags we track all potentially hydratable Elements of this type in a cache per Document. The cache is refreshed once each commit if and only if there is a title or meta hoistable hydrating. The caches are partitioned by a natural key for each type (href for link and content for meta). Then secondary attributes are checked to see if the potential match is matchable. For link we check `rel`, `title`, and `crossorigin`. These should provide enough entropy that we never have collisions except is contrived cases and even then it should not affect functionality of the page. This should also be tolerant of links being injected in arbitrary places in the Document by 3rd party scripts and browser extensions For meta we check `name`, `property`, `http-equiv`, and `charset`. These should provide enough entropy that we don't have meaningful collisions. It is concievable with og tags that there may be true duplciates `<meta property="og:image:size:height" content="100" />` but even if we did bind to the wrong instance meta tags are typically only read from SSR by bots and rarely inserted by 3rd parties so an adverse functional outcome is not expected.
2023-03-06 19:52:35 -08:00
"467": "Update hook called on initial render. This is likely a bug in React. Please file an issue.",
[Flight Reply] Add Reply Encoding (#26360) This adds `encodeReply` to the Flight Client and `decodeReply` to the Flight Server. Basically, it's a reverse Flight. It serializes values passed from the client to the server. I call this a "Reply". The tradeoffs and implementation details are a bit different so it requires its own implementation but is basically a clone of the Flight Server/Client but in reverse. Either through callServer or ServerContext. The goal of this project is to provide the equivalent serialization as passing props through RSC to client. Except React Elements and Components and such. So that you can pass a value to the client and back and it should have the same serialization constraints so when we add features in one direction we should mostly add it in the other. Browser support for streaming request bodies are currently very limited in that only Chrome supports it. So this doesn't produce a ReadableStream. Instead `encodeReply` produces either a JSON string or FormData. It uses a JSON string if it's a simple enough payload. For advanced features it uses FormData. This will also let the browser stream things like File objects (even though they're not yet supported since it follows the same rules as the other Flight). On the server side, you can either consume this by blocking on generating a FormData object or you can stream in the `multipart/form-data`. Even if the client isn't streaming data, the network does. On Node.js busboy seems to be the canonical library for this, so I exposed a `decodeReplyFromBusboy` in the Node build. However, if there's ever a web-standard way to stream form data, or if a library wins in that space we can support it. We can also just build a multipart parser that takes a ReadableStream built-in. On the server, server references passed as arguments are loaded from Node or Webpack just like the client or SSR does. This means that you can create higher order functions on the client or server. This can be tokenized when done from a server components but this is a security implication as it might be tempting to think that these are not fungible but you can swap one function for another on the client. So you have to basically treat an incoming argument as insecure, even if it's a function. I'm not too happy with the naming parity: Encode `server.renderToReadableStream` Decode: `client.createFromFetch` Decode `client.encodeReply` Decode: `server.decodeReply` This is mainly an implementation details of frameworks but it's annoying nonetheless. This comes from that `renderToReadableStream` does do some "rendering" by unwrapping server components etc. The `create` part comes from the parity with Fizz/Fiber where you `render` on the server and `create` a root on the client. Open to bike-shedding this some more. --------- Co-authored-by: Josh Story <josh.c.story@gmail.com>
2023-03-10 11:36:15 -05:00
"468": "getNodesForType encountered a type it did not expect: \"%s\". This is a bug in React.",
"469": "Client Functions cannot be passed directly to Server Functions. Only Functions passed from the Server can be passed back again.",
"470": "Only global symbols received from Symbol.for(...) can be passed to Server Functions. The symbol Symbol.for(%s) cannot be found among global symbols.",
"471": "BigInt (%s) is not yet supported as an argument to a Server Function.",
"472": "Type %s is not supported as an argument to a Server Function.",
Check if suspensey instance resolves in immediate task (#26427) 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.
2023-03-20 12:35:10 -04:00
"473": "React doesn't accept base64 encoded file uploads because we don't except form data passed from a browser to ever encode data that way. If that's the wrong assumption, we can easily fix it.",
"474": "Suspense Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React.",
"475": "Internal React Error: suspendedState null when it was expected to exists. Please report this as a React bug.",
[Float][Flight] Flight support for Float (#26502) Stacked on #26557 Supporting Float methods such as ReactDOM.preload() are challenging for flight because it does not have an easy means to convey direct executions in other environments. Because the flight wire format is a JSON-like serialization that is expected to be rendered it currently only describes renderable elements. We need a way to convey a function invocation that gets run in the context of the client environment whether that is Fizz or Fiber. Fiber is somewhat straightforward because the HostDispatcher is always active and we can just have the FlightClient dispatch the serialized directive. Fizz is much more challenging becaue the dispatcher is always scoped but the specific request the dispatch belongs to is not readily available. Environments that support AsyncLocalStorage (or in the future AsyncContext) we will use this to be able to resolve directives in Fizz to the appropriate Request. For other environments directives will be elided. Right now this is pragmatic and non-breaking because all directives are opportunistic and non-critical. If this changes in the future we will need to reconsider how widespread support for async context tracking is. For Flight, if AsyncLocalStorage is available Float methods can be called before and after await points and be expected to work. If AsyncLocalStorage is not available float methods called in the sync phase of a component render will be captured but anything after an await point will be a noop. If a float call is dropped in this manner a DEV warning should help you realize your code may need to be modified. This PR also introduces a way for resources (Fizz) and hints (Flight) to flush even if there is not active task being worked on. This will help when Float methods are called in between async points within a function execution but the task is blocked on the entire function finishing. This PR also introduces deduping of Hints in Flight using the same resource keys used in Fizz. This will help shrink payload sizes when the same hint is attempted to emit over and over again
2023-04-21 20:45:51 -07:00
"476": "Expected the form instance to be a HostComponent. This is a bug in React.",
"477": "React Internal Error: processHintChunk is not implemented for Native-Relay. The fact that this method was called means there is a bug in React.",
"478": "Thenable should have already resolved. This is a bug in React.",
"479": "Cannot update optimistic state while rendering.",
"480": "File/Blob fields are not yet supported in progressive forms. Will fallback to client hydration.",
Detect crashes caused by Async Client Components (#27019) Suspending with an uncached promise is not yet supported. We only support suspending on promises that are cached between render attempts. (We do plan to partially support this in the future, at least in certain constrained cases, like during a route transition.) This includes the case where a component returns an uncached promise, which is effectively what happens if a Client Component is authored using async/await syntax. This is an easy mistake to make in a Server Components app, because async/await _is_ available in Server Components. In the current behavior, this can sometimes cause the app to crash with an infinite loop, because React will repeatedly keep trying to render the component, which will result in a fresh promise, which will result in a new render attempt, and so on. We have some strategies we can use to prevent this — during a concurrent render, we can suspend the work loop until the promise resolves. If it's not a concurrent render, we can show a Suspense fallback and try again at concurrent priority. There's one case where neither of these strategies work, though: during a sync render when there's no parent Suspense boundary. (We refer to this as the "shell" of the app because it exists outside of any loading UI.) Since we don't have any great options for this scenario, we should at least error gracefully instead of crashing the app. So this commit adds a detection mechanism for render loops caused by async client components. The way it works is, if an app suspends repeatedly in the shell during a synchronous render, without committing anything in between, we will count the number of attempts and eventually trigger an error once the count exceeds a threshold. In the future, we will consider ways to make this case a warning instead of a hard error. See https://github.com/facebook/react/issues/26801 for more details.
2023-06-29 16:05:00 -04:00
"481": "Tried to encode a Server Action from a different instance than the encoder is from. This is a bug in React.",
"482": "An unknown Component is an async Client Component. Only Server Components can be async at the moment. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server.",
Add Postpone API (#27238) This adds an experimental `unstable_postpone(reason)` API. Currently we don't have a way to model effectively an Infinite Promise. I.e. something that suspends but never resolves. The reason this is useful is because you might have something else that unblocks it later. E.g. by updating in place later, or by client rendering. On the client this works to model as an Infinite Promise (in fact, that's what this implementation does). However, in Fizz and Flight that doesn't work because the stream needs to end at some point. We don't have any way of knowing that we're suspended on infinite promises. It's not enough to tag the promises because you could await those and thus creating new promises. The only way we really have to signal this through a series of indirections like async functions, is by throwing. It's not 100% safe because these values can be caught but it's the best we can do. Effectively `postpone(reason)` behaves like a built-in [Catch Boundary](https://github.com/facebook/react/pull/26854). It's like `raise(Postpone, reason)` except it's built-in so it needs to be able to be encoded and caught by Suspense boundaries. In Flight and Fizz these behave pretty much the same as errors. Flight just forwards it to retrigger on the client. In Fizz they just trigger client rendering which itself might just postpone again or fill in the value. The difference is how they get logged. In Flight and Fizz they log to `onPostpone(reason)` instead of `onError(error)`. This log is meant to help find deopts on the server like finding places where you fall back to client rendering. The reason that you pass in is for that purpose to help the reason for any deopts. I do track the stack trace in DEV but I don't currently expose it to `onPostpone`. This seems like a limitation. It might be better to expose the Postpone object which is an Error object but that's more of an implementation detail. I could also pass it as a second argument. On the client after hydration they don't get passed to `onRecoverableError`. There's no global `onPostpone` API to capture postponed things on the client just like there's no `onError`. At that point it's just assumed to be intentional. It doesn't have any `digest` or reason passed to the client since it's not logged. There are some hacky solutions that currently just tries to reuse as much of the existing code as possible but should be more properly implemented. - Fiber is currently just converting it to a fake Promise object so that it behaves like an infinite Promise. - Fizz is encoding the magic digest string `"POSTPONE"` in the HTML so we know to ignore it but it should probably just be something neater that doesn't share namespace with digests. Next I plan on using this in the `/static` entry points for additional features. Why "postpone"? It's basically a synonym to "defer" but we plan on using "defer" for other purposes and it's overloaded anyway.
2023-08-17 13:26:14 -04:00
"483": "Hooks are not supported inside an async component. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server.",
"484": "A Server Component was postponed. The reason is omitted in production builds to avoid leaking sensitive details.",
"485": "Cannot update form state while rendering.",
"486": "It should not be possible to postpone at the root. This is a bug in React.",
"487": "We should not have any resumable nodes in the shell. This is a bug in React.",
"488": "Couldn't find all resumable slots by key/index during replaying. The tree doesn't match so React will fallback to client rendering.",
"489": "Expected the resume to render <%s> in this slot but instead it rendered <%s>. The tree doesn't match so React will fallback to client rendering.",
"490": "Expected the resume to render <%s> in this slot but instead it rendered <%s>. The tree doesn't match so React will fallback to client rendering.",
"491": "It should not be possible to postpone both at the root of an element as well as a slot below. This is a bug in React.",
[Flight] Taint APIs (#27445) This lets a registered object or value be "tainted", which we block from crossing the serialization boundary. It's only allowed to stay in-memory. This is an extra layer of protection against mistakes of transferring data from a data access layer to a client. It doesn't provide perfect protection, because it doesn't trace through derived values and substrings. So it shouldn't be used as the only security layer but more layers are better. `taintObjectReference` is for specific object instances, not any nested objects or values inside that object. It's useful to avoid specific objects from getting passed as is. It ensures that you don't accidentally leak values in a specific context. It can be for security reasons like tokens, privacy reasons like personal data or performance reasons like avoiding passing large objects over the wire. It might be privacy violation to leak the age of a specific user, but the number itself isn't blocked in any other context. As soon as the value is extracted and passed specifically without the object, it can therefore leak. `taintUniqueValue` is useful for high entropy values such as hashes, tokens or crypto keys that are very unique values. In that case it can be useful to taint the actual primitive values themselves. These can be encoded as a string, bigint or typed array. We don't currently check for this value in a substring or inside other typed arrays. Since values can be created from different sources they don't just follow garbage collection. In this case an additional object must be provided that defines the life time of this value for how long it should be blocked. It can be `globalThis` for essentially forever, but that risks leaking memory for ever when you're dealing with dynamic values like reading a token from a database. So in that case the idea is that you pass the object that might end up in cache. A request is the only thing that is expected to do any work. The principle is that you can derive values from out of a tainted entry during a request. Including stashing it in a per request cache. What you can't do is store a derived value in a global module level cache. At least not without also tainting the object.
2023-10-02 13:55:39 -04:00
"492": "The \"react\" package in this environment is not configured correctly. The \"react-server\" condition must be enabled in any environment that runs React Server Components.",
"493": "To taint a value, a lifetime must be defined by passing an object that holds the value.",
"494": "taintUniqueValue cannot taint objects or functions. Try taintObjectReference instead.",
"495": "Cannot taint a %s because the value is too general and not unique enough to block globally.",
"496": "Only objects or functions can be passed to taintObjectReference. Try taintUniqueValue instead.",
"497": "Only objects or functions can be passed to taintObjectReference.",
"498": "Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.%s",
"499": "Only plain objects, and a few built-ins, can be passed to Server Functions. Classes or null prototypes are not supported.%s",
"500": "React expected a headers state to exist when emitEarlyPreloads was called but did not find it. This suggests emitEarlyPreloads was called more than once per request. This is a bug in React.",
"501": "The render was aborted with postpone when the shell is incomplete. Reason: %s",
"502": "Cannot read a Client Context from a Server Component.",
[Flight] Emit debug info for a Server Component (#28272) This adds a new DEV-only row type `D` for DebugInfo. If we see this in prod, that's an error. It can contain extra debug information about the Server Components (or Promises) that were compiled away during the server render. It's DEV-only since this can contain sensitive information (similar to errors) and since it'll be a lot of data, but it's worth using the same stream for simplicity rather than a side-channel. In this first pass it's just the Server Component's name but I'll keep adding more debug info to the stream, and it won't always just be a Server Component's stack frame. Each row can get more debug rows data streaming in as it resolves and renders multiple server components in a row. The data structure is just a side-channel and it would be perfectly fine to ignore the D rows and it would behave the same as prod. With this data structure though the data is associated with the row ID / chunk, so you can't have inline meta data. This means that an inline Server Component that doesn't get an ID otherwise will need to be outlined. The way I outline Server Components is using a direct reference where it's synchronous though so on the client side it behaves the same (i.e. there's no lazy wrapper in this case). In most cases the `_debugInfo` is on the Promises that we yield and we also expose this on the `React.Lazy` wrappers. In the case where it's a synchronous render it might attach this data to Elements or Arrays (fragments) too. In a future PR I'll wire this information up with Fiber to stash it in the Fiber data structures so that DevTools can pick it up. This property and the information in it is not limited to Server Components. The name of the property that we look for probably shouldn't be `_debugInfo` since it's semi-public. Should consider the name we use for that. If it's a synchronous render that returns a string or number (text node) then we don't have anywhere to attach them to. We could add a `React.Lazy` wrapper for those but I chose to prioritize keeping the data structure untouched. Can be useful if you use Server Components to render data instead of React Nodes.
2024-02-08 08:01:32 -08:00
"503": "Cannot use() an already resolved Client Reference.",
"504": "Failed to read a RSC payload created by a development version of React on the server while using a production version on the client. Always use matching versions on the server and the client.",
"505": "Cannot render an Async Component, Promise or React.Lazy inside React.Children. We recommend not iterating over children and just rendering them plain.",
"506": "Functions are not valid as a child of Client Components. This may happen if you return %s instead of <%s /> from render. Or maybe you meant to call this function rather than return it.%s",
"507": "Expected the last optional `callback` argument to be a function. Instead received: %s.",
"508": "The first argument must be a React class instance. Instead received: %s.",
[Flight] Encode React Elements in Replies as Temporary References (#28564) Currently you can accidentally pass React Element to a Server Action. It warns but in prod it actually works because we can encode the symbol and otherwise it's mostly a plain object. It only works if you only pass host components and no function props etc. which makes it potentially error later. The first thing this does it just early hard error for elements. I made Lazy work by unwrapping though since that will be replaced by Promises later which works. Our protocol is not fully symmetric in that elements flow from Server -> Client. Only the Server can resolve Components and only the client should really be able to receive host components. It's not intended that a Server can actually do something with them other than passing them to the client. In the case of a Reply, we expect the client to be stateful. It's waiting for a response. So anything we can't serialize we can still pass by reference to an in memory object. So I introduce the concept of a TemporaryReferenceSet which is an opaque object that you create before encoding the reply. This then stashes any unserializable values in this set and encode the slot by id. When a new response from the Action then returns we pass the same temporary set into the parser which can then restore the objects. This lets you pass a value by reference to the server and back into another slot. For example it can be used to render children inside a parent tree from a server action: ``` export async function Component({ children }) { "use server"; return <div>{children}</div>; } ``` (You wouldn't normally do this due to the waterfalls but for advanced cases.) A common scenario where this comes up accidentally today is in `useActionState`. ``` export function action(state, formData) { "use server"; if (errored) { return <div>This action <strong>errored</strong></div>; } return null; } ``` ``` const [errors, formAction] = useActionState(action); return <div>{errors}<div>; ``` It feels like I'm just passing the JSX from server to client. However, because `useActionState` also sends the previous state *back* to the server this should not actually be valid. Before this PR this actually worked accidentally. You get a DEV warning but it used to work in prod. Once you do something like pass a client reference it won't work tho. We could perhaps make client references work by stashing where we got them from but it wouldn't work with all possible JSX. By adding temporary references to the action implementation this will work again - on the client. It'll also be more efficient since we don't send back the JSX content that you shouldn't introspect on the server anyway. However, a flaw here is that the progressive enhancement of this case won't work because we can't use temporary references for progressive enhancement since there's no in memory stash. What is worse is that it won't error if you hydrate. ~It also will error late in the example above because the first state is "undefined" so invoking the form once works - it errors on the second attempt when it tries to send the error state back again.~ It actually errors on the first invocation because we need to eagerly serialize "previous state" into the form. So at least that's better. I think maybe the solution to this particular pattern would be to allow JSX to serialize if you have no temporary reference set, and remember client references so that client references can be returned back to the server as client references. That way anything you could send from the server could also be returned to the server. But it would only deopt to serializing it for progressive enhancement. The consequence of that would be that there's a lot of JSX that might accidentally seem like it should work but it's only if you've gotten it from the server before that it works. This would have to have pair them somehow though since you can't take a client reference from one implementation of Flight and use it with another.
2024-03-19 16:59:52 -04:00
"509": "ReactDOM: Unsupported Legacy Mode API.",
"510": "React Element cannot be passed to Server Functions from the Client without a temporary reference set. Pass a TemporaryReferenceSet to the options.%s",
"511": "Missing a temporary reference set but the RSC response returned a temporary reference. Pass a temporaryReference option with the set that was used with the reply.",
"512": "The RSC response contained a reference that doesn't exist in the temporary reference set. Always pass the matching set that was used to create the reply when parsing its response.",
"513": "Cannot render a Client Context Provider on the Server. Instead, you can export a Client Component wrapper that itself renders a Client Context Provider.",
"514": "Cannot access %s on the server. You cannot dot into a temporary client reference from a server component. You can only pass the value through to the client.",
"515": "Cannot assign to a temporary client reference from a server module.",
[Flight Reply] Don't allow Symbols to be passed to a reply (#28610) As mentioned in #28609 there's a potential security risk if you allow a passed value to the server to spoof Elements because it allows a hacker to POST cross origin. This is only an issue if your framework allows this which it shouldn't but it seems like we should provide an extra layer of security here. ```js function action(errors, payload) { try { ... } catch (x) { return [newError].concat(errors); } } ``` ```js const [errors, formAction] = useActionState(action); return <div>{errors}</div>; ``` This would allow you to construct a payload where the previous "errors" set includes something like `<script src="danger.js" />`. We could block only elements from being received but it could potentially be a risk with creating other React types like Context too. We use symbols as a way to securely brand these. Most JS don't use this kind of branding with symbols like we do. They're generally properties which we don't support anyway. However in theory someone else could be using them like we do. So in an abundance of carefulness I just ban all symbols from being passed (except by temporary reference) - not just ours. This means that the format isn't fully symmetric even beyond just React Nodes. #28611 allows code that includes symbols/elements to continue working but may have to bail out to replaying instead of no JS sometimes. However, you still can't access the symbols inside the server - they're by reference only.
2024-03-21 16:53:02 -04:00
"516": "Attempted to call a temporary Client Reference from the server but it is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.",
"517": "Symbols cannot be passed to a Server Function without a temporary reference set. Pass a TemporaryReferenceSet to the options.%s",
Use a Wrapper Error for onRecoverableError with a "cause" Field for the real Error (#28736) We basically have four kinds of recoverable errors: - Hydration mismatches. - Server errored but client didn't. - Hydration render errored but client render didn't (in Root or Suspense boundary). - Concurrent render errored but synchronous render didn't. For the first three we log an additional error that the root or Suspense boundary didn't error. This provides some context about what happened. However, the problem is that for hydration mismatches that's unnecessary extra context that is confusing. We also don't log any additional context for concurrent render errors that could recover. This used to be the only recoverable error so it didn't need extra context but now we need to distinguish them. When we log these to `reportError` it's confusing to just see the error because you didn't see anything error on the page. It's also hard to group them together as one. In this PR, I remove the unnecessary context for hydration mismatches. For hydration and concurrent errors, I now wrap them in an error that describes that what happened but then use the new `cause` field to link the original error so we can keep that as the cause. The error that happened was that hydration client rendered or you deopted to sync render, the cause of that error is some other error. For server errors, we control the Error object so I already had added some context to that error object's message. Since we hide the message in prod, it's nice not to have the raw message in DEV neither. We could potentially split these into two errors for parity though.
2024-04-03 21:53:07 -04:00
"518": "Saw multiple hydration diff roots in a pass. This is a bug in React.",
"519": "Hydration Mismatch Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React.",
"520": "There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.",
"521": "flushSyncWork should not be called from builds that support legacy mode. This is a bug in React.",
[Flight] Encode ReadableStream and AsyncIterables (#28847) This adds support in Flight for serializing four kinds of streams: - `ReadableStream` with objects as a model. This is a single shot iterator so you can read it only once. It can contain any value including Server Components. Chunks are encoded as is so if you send in 10 typed arrays, you get the same typed arrays out on the other side. - Binary `ReadableStream` with `type: 'bytes'` option. This supports the BYOB protocol. In this mode, the receiving side just gets `Uint8Array`s and they can be split across any single byte boundary into arbitrary chunks. - `AsyncIterable` where the `AsyncIterator` function is different than the `AsyncIterable` itself. In this case we assume that this might be a multi-shot iterable and so we buffer its value and you can iterate it multiple times on the other side. We support the `return` value as a value in the single completion slot, but you can't pass values in `next()`. If you want single-shot, return the AsyncIterator instead. - `AsyncIterator`. These gets serialized as a single-shot as it's just an iterator. `AsyncIterable`/`AsyncIterator` yield Promises that are instrumented with our `.status`/`.value` convention so that they can be synchronously looped over if available. They are also lazily parsed upon read. We can't do this with `ReadableStream` because we use the native implementation of `ReadableStream` which owns the promises. The format is a leading row that indicates which type of stream it is. Then a new row with the same ID is emitted for every chunk. Followed by either an error or close row. `AsyncIterable`s can also be returned as children of Server Components and then they're conceptually the same as fragment arrays/iterables. They can't actually be used as children in Fizz/Fiber but there's a separate plan for that. Only `AsyncIterable` not `AsyncIterator` will be valid as children - just like sync `Iterable` is already supported but single-shot `Iterator` is not. Notably, neither of these streams represent updates over time to a value. They represent multiple values in a list. When the server stream is aborted we also close the underlying stream. However, closing a stream on the client, doesn't close the underlying stream. A couple of possible follow ups I'm not planning on doing right now: - [ ] Free memory by releasing the buffer if an Iterator has been exhausted. Single shots could be optimized further to release individual items as you go. - [ ] We could clean up the underlying stream if the only pending data that's still flowing is from streams and all the streams have cleaned up. It's not very reliable though. It's better to do cancellation for the whole stream - e.g. at the framework level. - [ ] Implement smarter Binary Stream chunk handling. Currently we wait until we've received a whole row for binary chunks and copy them into consecutive memory. We need this to preserve semantics when passing typed arrays. However, for binary streams we don't need that. We can just send whatever pieces we have so far.
2024-04-16 12:20:07 -04:00
"522": "Invalid form element. requestFormReset must be passed a form that was rendered by React.",
"523": "The render was aborted due to being postponed.",
"524": "Values cannot be passed to next() of AsyncIterables passed to Client Components.",
[Flight Reply] Encode Objects Returned to the Client by Reference (#29010) Stacked on #28997. We can use the technique of referencing an object by its row + property name path for temporary references - like we do for deduping. That way we don't need to generate an ID for temporary references. Instead, they can just be an opaque marker in the slot and it has the implicit ID of the row + path. Then we can stash all objects, even the ones that are actually available to read on the server, as temporary references. Without adding anything to the payload since the IDs are implicit. If the same object is returned to the client, it can be referenced by reference instead of serializing it back to the client. This also helps preserve object identity. We assume that the objects are immutable when they pass the boundary. I'm not sure if this is worth it but with this mechanism, if you return the `FormData` payload from a `useActionState` it doesn't have to be serialized on the way back to the client. This is a common pattern for having access to the last submission as "default value" to the form fields. However you can still control it by replacing it with another object if you want. In MPA mode, the temporary references are not configured and so it needs to be serialized in that case. That's required anyway for hydration purposes. I'm not sure if people will actually use this in practice though or if FormData will always be destructured into some other object like with a library that turns it into typed data, and back. If so, the object identity is lost.
2024-05-09 20:00:56 -04:00
"525": "A React Element from an older version of React was rendered. This is not supported. It can happen if:\n- Multiple copies of the \"react\" package is used.\n- A library pre-bundled an old copy of \"react\" or \"react/jsx-runtime\".\n- A compiler tries to \"inline\" JSX instead of using the runtime.",
"526": "Could not reference an opaque temporary reference. This is likely due to misconfiguring the temporaryReferences options on the server.",
[Fiber][Float] Error when a host fiber changes "flavor" (#29693) Host Components can exist as four semantic types 1. regular Components (Vanilla obv) 2. singleton Components 2. hoistable components 3. resources Each of these component types have their own rules related to mounting and reconciliation however they are not direclty modeled as their own unique fiber type. This is partly for code size but also because reconciling the inner type of these components would be in a very hot path in fiber creation and reconciliation and it's just not practical to do this logic check here. Right now we have three Fiber types used to implement these 4 concepts but we probably need to reconsider the model and think of Host Components as a single fiber type with an inner implementation. Once we do this we can regularize things like transitioning between a resource and a regular component or a singleton and a hoistable instance. The cases where these transitions happen today aren't particularly common but they can be observed and currently the handling of these transitions is incomplete at best and buggy at worst. The most egregious case is the link type. This can be a regular component (stylesheet without precedence) a hoistable component (non stylesheet link tags) or a resource (stylesheet with a precedence) and if you have a single jsx slot that tries to reconcile transitions between these types it just doesn't work well. This commit adds an error for when a Hoistable goes from Instance to Resource. Currently this is only possible for `<link>` elements going to and from stylesheets with precedence. Hopefully we'll be able to remove this error and implement as an inner type before we encounter new categories for the Hoistable types detecting type shifting to and from regular components is harder to do efficiently because we don't want to reevaluate the type on every update for host components which is currently not required and would add overhead to a very hot path singletons can't really type shift in their one practical implementation (DOM) so they are only a problem in theroy not practice
2024-06-03 07:47:45 -07:00
"527": "Incompatible React versions: The \"react\" and \"react-dom\" packages must have the exact same version. Instead got:\n - react: %s\n - react-dom: %s\nLearn more: https://react.dev/warnings/version-mismatch",
"528": "Expected <link> not to update to be updated to a stylesheet with precedence. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.%s",
"529": "Expected stylesheet with precedence to not be updated to a different kind of <link>. Check the `rel`, `href`, and `precedence` props of this component. Alternatively, check whether two different <link> components render in the same slot or share the same key.%s",
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
2024-06-27 18:09:40 +02:00
"530": "The render was aborted by the server with a promise.",
"531": "react-markup is not supported outside a React Server Components environment.",
"532": "Attempted to render a Client Component from renderToHTML. This is not supported since it will never hydrate. Only render Server Components with renderToHTML.",
"533": "Attempted to render a Server Action from renderToHTML. This is not supported since it varies by version of the app. Use a fixed URL for any forms instead.",
"534": "renderToHTML should not have emitted Client References. This is a bug in React.",
"535": "renderToHTML should not have emitted Server References. This is a bug in React.",
"536": "Cannot pass ref in renderToHTML because they will never be hydrated.",
"537": "Cannot pass event handlers (%s) in renderToHTML because the HTML will never be hydrated so they can never get called.",
"538": "Cannot use state or effect Hooks in renderToHTML because this component will never be hydrated.",
[Flight] Allow String Chunks to Passthrough in Node streams and renderToMarkup (#30131) It can be efficient to accept raw string chunks to pass through a stream instead of encoding them into a binary copy first. Previously our Flight parsers didn't accept receiving string chunks. That's partly because we sometimes need to encode binary chunks anyway so string only transport isn't enough but some chunks can be strings. This adds a partial ability for chunks to be received as strings. However, accepting strings comes with some downsides. E.g. if the strings are split up we need to buffer it which compromises the perf for the common case. If the chunk represents binary data, then we'd need to encode it back into a typed array which would require a TextEncoder dependency in the parser. If the string chunk represents a byte length encoded string we don't know how many unicode characters to read without measuring them in terms of binary - also requiring a TextEncoder. This PR is mainly intended for use for pass-through within the same memory. We can simplify the implementation by assuming that any string chunk is passed as the original chunk. This requires that the server stream config doesn't arbitrarily concatenate strings (e.g. large strings should not be concatenated which is probably a good heuristic anyway). It also means that this is not suitable to be used with for example receiving string chunks on the client by passing them through SSR hydration data - except if the encoding that way was only used with chunks that were already encoded as strings by Flight. Web streams mostly just work on binary data anyway so they can't use this. In Node.js streams we concatenate precomputed and small strings into larger buffers. It might make sense to do that using string ropes instead. However, in the meantime we can at least pass large strings that are outside our buffer view size as raw strings. There's no benefit to us eagerly encoding those. Also, let Node accept string chunks as long as they're following our expected constraints. This lets us test the mixed protocol using pass-throughs. This can also be useful when the RSC server is in the same environment as the SSR server as they don't have to go from strings to typed arrays back to strings. Now we can also use this in the pass-through used in renderToMarkup. This lets us avoid the dependency on TextDecoder/TextEncoder in that package.
2024-07-03 13:25:04 -04:00
"539": "Binary RSC chunks cannot be encoded as strings. This is a bug in the wiring of the React streams.",
"540": "String chunks need to be passed in their original shape. Not split into smaller string chunks. This is a bug in the wiring of the React streams.",
"541": "Compared context values must be arrays",
"542": "Suspense Exception: This is not a real error! It's an implementation detail of `useActionState` to interrupt the current render. You must either rethrow it immediately, or move the `useActionState` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary.",
Add <ViewTransition> Component (#31975) This will provide the opt-in for using [View Transitions](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) in React. View Transitions only trigger for async updates like `startTransition`, `useDeferredValue`, Actions or `<Suspense>` revealing from fallback to content. Synchronous updates provide an opt-out but also guarantee that they commit immediately which View Transitions can't. There's no need to opt-in to View Transitions at the "cause" side like event handlers or actions. They don't know what UI will change and whether that has an animated transition described. Conceptually the `<ViewTransition>` component is like a DOM fragment that transitions its children in its own isolate/snapshot. The API works by wrapping a DOM node or inner component: ```js import {ViewTransition} from 'react'; <ViewTransition><Component /></ViewTransition> ``` The default is `name="auto"` which will automatically assign a `view-transition-name` to the inner DOM node. That way you can add a View Transition to a Component without controlling its DOM nodes styling otherwise. A difference between this and the browser's built-in `view-transition-name: auto` is that switching the DOM nodes within the `<ViewTransition>` component preserves the same name so this example cross-fades between the DOM nodes instead of causing an exit and enter: ```js <ViewTransition>{condition ? <ComponentA /> : <ComponentB />}</ViewTransition> ``` This becomes especially useful with `<Suspense>` as this example cross-fades between Skeleton and Content: ```js <ViewTransition> <Suspense fallback={<Skeleton />}> <Content /> </Suspense> </ViewTransition> ``` Where as this example triggers an exit of the Skeleton and an enter of the Content: ```js <Suspense fallback={<ViewTransition><Skeleton /></ViewTransition>}> <ViewTransition><Content /></ViewTransition> </Suspense> ``` Managing instances and keys becomes extra important. You can also specify an explicit `name` property for example for animating the same conceptual item from one page onto another. However, best practices is to property namespace these since they can easily collide. It's also useful to add an `id` to it if available. ```js <ViewTransition name="my-shared-view"> ``` The model in general is the same as plain `view-transition-name` except React manages a set of heuristics for when to apply it. A problem with the naive View Transitions model is that it overly opts in every boundary that *might* transition into transitioning. This is leads to unfortunate effects like things floating around when unrelated updates happen. This leads the whole document to animate which means that nothing is clickable in the meantime. It makes it not useful for smaller and more local transitions. Best practice is to add `view-transition-name` only right before you're about to need to animate the thing. This is tricky to manage globally on complex apps and is not compositional. Instead we let React manage when a `<ViewTransition>` "activates" and add/remove the `view-transition-name`. This is also when React calls `startViewTransition` behind the scenes while it mutates the DOM. I've come up with a number of heuristics that I think will make a lot easier to coordinate this. The principle is that only if something that updates that particular boundary do we activate it. I hope that one day maybe browsers will have something like these built-in and we can remove our implementation. A `<ViewTransition>` only activates if: - If a mounted Component renders a `<ViewTransition>` within it outside the first DOM node, and it is within the viewport, then that ViewTransition activates as an "enter" animation. This avoids inner "enter" animations trigger when the parent mounts. - If an unmounted Component had a `<ViewTransition>` within it outside the first DOM node, and it was within the viewport, then that ViewTransition activates as an "exit" animation. This avoids inner "exit" animations triggering when the parent unmounts. - If an explicitly named `<ViewTransition name="...">` is deep within an unmounted tree and one with the same name appears in a mounted tree at the same time, then both are activated as a pair, but only if they're both in the viewport. This avoids these triggering "enter" or "exit" animations when going between parents that don't have a pair. - If an already mounted `<ViewTransition>` is visible and a DOM mutation, that might affect how it's painted, happens within its children but outside any nested `<ViewTransition>`. This allows it to "cross-fade" between its updates. - If an already mounted `<ViewTransition>` resizes or moves as the result of direct DOM nodes siblings changing or moving around. This allows insertion, deletion and reorders into a list to animate all children. It is only within one DOM node though, to avoid unrelated changes in the parent to trigger this. If an item is outside the viewport before and after, then it's skipped to avoid things flying across the screen. - If a `<ViewTransition>` boundary changes size, due to a DOM mutation within it, then the parent activates (or the root document if there are no more parents). This ensures that the container can cross-fade to avoid abrupt relayout. This can be avoided by using absolutely positioned children. When this can avoid bubbling to the root document, whatever is not animating is still responsive to clicks during the transition. Conceptually each DOM node has its own default that activates the parent `<ViewTransition>` or no transition if the parent is the root. That means that if you add a DOM node like `<div><ViewTransition><Component /></ViewTransition></div>` this won't trigger an "enter" animation since it was the div that was added, not the ViewTransition. Instead, it might cause a cross-fade of the parent ViewTransition or no transition if it had no parent. This ensures that only explicit boundaries perform coarse animations instead of every single node which is really the benefit of the View Transitions model. This ends up working out well for simple cases like switching between two pages immediately while transitioning one floating item that appears on both pages. Because only the floating item transitions by default. Note that it's possible to add manual `view-transition-name` with CSS or `style={{ viewTransitionName: 'auto' }}` that always transitions as long as something else has a `<ViewTransition>` that activates. For example a `<ViewTransition>` can wrap a whole page for a cross-fade but inside of it an explicit name can be added to something to ensure it animates as a move when something relates else changes its layout. Instead of just cross-fading it along with the Page which would be the default. There's more PRs coming with some optimizations, fixes and expanded APIs. This first PR explores the above core heuristic. --------- Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-01-08 12:11:18 -05:00
"543": "Expected a ResourceEffectUpdate to be pushed together with ResourceEffectIdentity. This is a bug in React.",
[Fizz] Support Suspense boundaries anywhere (#32069) Suspense is meant to be composable but there has been a lonstanding limitation with using Suspense above the `<body>` tag of an HTML document due to peculiarities of how HTML is parsed. For instance if you used Suspense to render an entire HTML document and had a fallback that might flush an alternate Document the comment nodes which describe this boundary scope won't be where they need to be in the DOM for client React to properly hydrate them. This is somewhat a problem of our own making in that we have a concept of a Preamble and we leave the closing body and html tags behind until streaming has completed which produces a valid HTML document that also matches the DOM structure that would be parsed from it. However Preambles as a concept are too important to features like Float to imagine moving away from this model and so we can either choose to just accept that you cannot use Suspense anywhere except inside the `<body>` or we can build special support for Suspense into react-dom that has a coherent semantic with how HTML documents are written and parsed. This change implements Suspense support for react-dom/server by correctly serializing boundaries during rendering, prerendering, and resumgin on the server. It does not yet support Suspense everywhere on the client but this will arrive in a subsequent change. In practice Suspense cannot be used above the `<body>` tag today so this is not a breaking change since no programs in the wild could be using this feature anyway. React's streaming rendering of HTML doesn't lend itself to replacing the contents of the documentElement, head, or body of a Document. These are already special cased in fiber as HostSingletons and similarly for Fizz the values we render for these tags must never be updated by the Fizz runtime once written. To accomplish these we redefine the Preamble as the tags that represent these three singletons plus the contents of the document.head. If you use Suspense above any part of the Preamble then nothing will be written to the destination until the boundary is no longer pending. If the boundary completes then the preamble from within that boudnary will be output. If the boundary postpones or errors then the preamble from the fallback will be used instead. Additionally, by default anything that is not part of the preamble is implicitly in body scope. This leads to the somewhat counterintuitive consequence that the comment nodes we use to mark the borders of a Suspense boundary in Fizz can appear INSIDE the preamble that was rendered within it. ```typescript render(( <Suspense> <html lang="en"> <body> <div>hello world</div> </body> </html> </Suspense> )) ``` will produce an HTML document like this ```html <!DOCTYPE html> <html lang="en"> <head></head> <body> <!--$--> <-- this is the comment Node representing the outermost Suspense <div>hello world</div> <$--/$--> </body> </html> ``` Later when I update Fiber to support Suspense anywhere hydration will similarly start implicitly in the document body when the root is part of the preamble (the document or one of it's singletons).
2025-01-17 10:54:11 -08:00
"544": "Found a pair with an auto name. This is a bug in React.",
"545": "The %s tag may only be rendered once.",
Add useSwipeTransition Hook Behind Experimental Flag (#32373) This Hook will be used to drive a View Transition based on a gesture. ```js const [value, startGesture] = useSwipeTransition(prev, current, next); ``` The `enableSwipeTransition` flag will depend on `enableViewTransition` flag but we may decide to ship them independently. This PR doesn't do anything interesting yet. There will be a lot more PRs to build out the actual functionality. This is just wiring up the plumbing for the new Hook. This first PR is mainly concerned with how the whole starts (and stops). The core API is the `startGesture` function (although there will be other conveniences added in the future). You can call this to start a gesture with a source provider. You can call this multiple times in one event to batch multiple Hooks listening to the same provider. However, each render can only handle one source provider at a time and so it does one render per scheduled gesture provider. This uses a separate `GestureLane` to drive gesture renders by marking the Hook as having an update on that lane. Then schedule a render. These renders should be blocking and in the same microtask as the `startGesture` to ensure it can block the paint. So it's similar to sync. It may not be possible to finish it synchronously e.g. if something suspends. If so, it just tries again later when it can like any other render. This can also happen because it also may not be possible to drive more than one gesture at a time like if we're limited to one View Transition per document. So right now you can only run one gesture at a time in practice. These renders never commit. This means that we can't clear the `GestureLane` the normal way. Instead, we have to clear only the root's `pendingLanes` if we don't have any new renders scheduled. Then wait until something else updates the Fiber after all gestures on it have stopped before it really clears.
2025-02-13 16:06:01 -05:00
"546": "useEffect CRUD overload is not enabled in this build of React.",
"547": "startGesture cannot be called during server rendering.",
"548": "Finished rendering the gesture lane but there were no pending gestures. React should not have started a render in this case. This is a bug in React.",
"549": "Cannot start a gesture with a disconnected AnimationTimeline.",
"550": "startGestureTransition is not yet supported in react-art.",
"551": "startGestureTransition is not yet supported in React Native.",
"552": "Cannot use a startGestureTransition() on a detached root.",
Add startGestureTransition API (#32785) Stacked on #32783. This will replace [the `useSwipeTransition` API](https://github.com/facebook/react/pull/32373). Instead, of a special Hook, you can make updates to `useOptimistic` Hooks within the `startGestureTransition` scope. ``` import {unstable_startGestureTransition as startGestureTransition} from 'react'; const cancel = startGestureTransition(timeline, () => { setOptimistic(...); }, options); ``` There are some downsides to this like you can't define two directions as once and there's no "standard" direction protocol. It's instead up to libraries to come up with their own conventions (although we can suggest some). The convention is still that a gesture recognizer has two props `action` and `gesture`. The `gesture` prop is a Gesture concept which now behaves more like an Action but 1) it can't be async 2) it shouldn't have side-effects. For example you can't call `setState()` in it except on `useOptimistic` since those can be reverted if needed. The `action` is invoked with whatever side-effects you want after the gesture fulfills. This is isomorphic and not associated with a specific renderer nor root so it's a bit more complicated. To implement this I unify with the `ReactSharedInternal.T` property to contain a regular Transition or a Gesture Transition (the `gesture` field). The benefit of this unification means that every time we override this based on some scope like entering `flushSync` we also override the `startGestureTransition` scope. We just have to be careful when we read it to check the `gesture` field to know which one it is. (E.g. I error for setState / requestFormReset.) The other thing that's unique is the `cancel` return value to know when to stop the gesture. That cancellation is no longer associated with any particular Hook. It's more associated with the scope of the `startGestureTransition`. Since the schedule of whether a particular gesture has rendered or committed is associated with a root, we need to somehow associate any scheduled gestures with a root. We could track which roots we update inside the scope but instead, I went with a model where I check all the roots and see if there's a scheduled gesture matching the timeline. This means that you could "retain" a gesture across roots. Meaning this wouldn't cancel until both are cancelled: ``` const cancelA = startGestureTransition(timeline, () => { setOptimisticOnRootA(...); }, options); const cancelB = startGestureTransition(timeline, () => { setOptimisticOnRootB(...); }, options); ``` It's more like it's a global transition than associated with the roots that were updated. Optimistic updates mostly just work but I now associate them with a specific "ScheduledGesture" instance since we can only render one at a time and so if it's not the current one, we leave it for later. Clean up of optimistic updates is now lazy rather than when we cancel. Allowing the cancel closure not to have to be associated with each particular update.
2025-03-31 20:05:50 -04:00
"553": "A Timeline is required as the first argument to startGestureTransition.",
"554": "Cannot setState on regular state inside a startGestureTransition. Gestures can only update the useOptimistic() hook. There should be no side-effects associated with starting a Gesture until its Action is invoked. Move side-effects to the Action instead.",
"555": "Cannot requestFormReset() inside a startGestureTransition. There should be no side-effects associated with starting a Gesture until its Action is invoked. Move side-effects to the Action instead.",
"556": "Expected prepareToHydrateHostActivityInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.",
"557": "Expected to have a hydrated activity instance. This error is likely caused by a bug in React. Please file an issue.",
"558": "Client rendering an Activity suspended it again. This is a bug in React.",
"559": "Expected to find a host node. This is a bug in React.",
"560": "Cannot use a startGestureTransition() with a comment node root."
}