captureOwnerStack
captureOwnerStack
reads the current owner Component stack and returns it as a string if available.
captureOwnerStack();
Reference
captureOwnerStack()
Call captureOwnerStack
to get the current owner Component stack.
import * as React from 'react';
function Component() {
if (process.env.NODE_ENV !== 'production') {
const ownerStack = React.captureOwnerStack();
console.log(ownerStack);
}
}
Parameters
captureOwnerStack
does not take any parameters.
Returns
captureOwnerStack
returns string | null
.
If no owner stack is available, it returns an empty string.
Outside of development builds, null
is returned.
Owner Component stacks vs parent Component stacks
The owner Component stack is different from the parent Component stack available error handlers like errorInfo.componentStack
in onUncaughtError
.
For example, consider the following code:
import * as React from 'react';
import * as ReactDOMClient from 'react-dom/client';
function SubComponent({disabled}) {
if (disabled) {
throw new Error('disabled');
}
}
function Component({label}) {
return (
<fieldset>
<legend>{label}</legend>
<SubComponent key={label} disabled={label === 'disabled'} />
</fieldset>
);
}
function Navigation() {
return null;
}
function App({children}) {
return (
<React.Suspense fallback="loading...">
<main>
<Navigation />
{children}
</main>
</React.Suspense>
);
}
createRoot(document.createElement('div')).render(
<App>
<Component label="disabled" />
</App>
);
SubComponent
would throw an error.
The parent component stack of that error would be
at SubComponent
at fieldset
at Component
at main
at React.Suspense
at App
However, the owner stack would only read
at SubComponent
at Component
Neither App
nor the DOM components (e.g. fieldset
) are considered owners in this stack since they didn’t contribute to “creating” the node containing SubComponent
. App
and DOM components only forwarded the node. App
just rendered the children
node as opposed to Component
which created a node containing SubComponent
via <SubComponent />
.
Neither Navigation
nor legend
are in the stack at all since it’s only a sibling to a node containing <SubComponent />
.
When to use which
The parent stack is useful for contextual information e.g. React.Suspense
, React Context, or <form>
.
The owner stack is useful for tracing the flow of props. Owner stacks are equivalent to call stacks if all JSX would be converted to direct function calls e.g. Component({label: "disabled"})
instead of <Component label="disabled" />
.
Usage
Expanding error stacks
In addition to the stack trace of the error itself, you can use captureOwnerStack
to append the stack trace of the owner Component.
This can help trace the error especially when the error is caused by props. The owner Component stack helps trace the flow of props.
import { captureOwnerStack } from 'react'
import { hydrateRoot } from 'react-dom/client';
const root = hydrateRoot(
document.getElementById('root'),
<App />,
{
onCaughtError: (error, errorInfo) => {
if (process.env.NODE_ENV !== 'production') {
const ownerStack = captureOwnerStack();
error.stack += ownerStack;
}
console.error(
'Caught error',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);