captureOwnerStack
在开发中读取当前的 Owner Stack,如果可用则将其作为字符串返回。
¥captureOwnerStack
reads the current Owner Stack in development and returns it as a string if available.
const stack = captureOwnerStack();
参考
¥Reference
captureOwnerStack()
调用 captureOwnerStack
以获取当前的 Owner Stack。
¥Call captureOwnerStack
to get the current Owner Stack.
import * as React from 'react';
function Component() {
if (process.env.NODE_ENV !== 'production') {
const ownerStack = React.captureOwnerStack();
console.log(ownerStack);
}
}
参数
¥Parameters
captureOwnerStack
没有参数。
¥captureOwnerStack
does not take any parameters.
返回
¥Returns
captureOwnerStack
返回 string | null
。
¥captureOwnerStack
returns string | null
.
Owner Stacks 可用于
¥Owner Stacks are available in
-
组件渲染
¥Component render
-
效果(例如
useEffect
)¥Effects (e.g.
useEffect
) -
React 的事件处理程序(例如
<button onClick={...} />
)¥React’s event handlers (e.g.
<button onClick={...} />
) -
React 错误处理程序(React Root 选项
onCaughtError
、onRecoverableError
和onUncaughtError
)¥React error handlers (React Root options
onCaughtError
,onRecoverableError
, andonUncaughtError
)
如果没有可用的所有者堆栈,则返回 null
(参见 故障排除:所有者堆栈为 null
)。
¥If no Owner Stack is available, null
is returned (see Troubleshooting: The Owner Stack is null
).
注意事项
¥Caveats
-
Owner Stacks 仅在开发中可用。
captureOwnerStack
将始终在开发之外返回null
。¥Owner Stacks are only available in development.
captureOwnerStack
will always returnnull
outside of development.
深入研究
¥Owner Stack vs Component Stack
所有者堆栈与 errorInfo.componentStack
in onUncaughtError
等 React 错误处理程序中可用的组件堆栈不同。
¥The Owner Stack is different from the Component Stack available in React error handlers like errorInfo.componentStack
in onUncaughtError
.
例如,请考虑以下代码:
¥For example, consider the following code:
import {captureOwnerStack} from 'react'; import {createRoot} from 'react-dom/client'; import App, {Component} from './App.js'; import './styles.css'; createRoot(document.createElement('div'), { onUncaughtError: (error, errorInfo) => { // The stacks are logged instead of showing them in the UI directly to // highlight that browsers will apply sourcemaps to the logged stacks. // Note that sourcemapping is only applied in the real browser console not // in the fake one displayed on this page. // Press "fork" to be able to view the sourcemapped stack in a real console. console.log(errorInfo.componentStack); console.log(captureOwnerStack()); }, }).render( <App> <Component label="disabled" /> </App> );
SubComponent
将抛出错误。该错误的组件堆栈将是
¥SubComponent
would throw an error.
The 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 Component
App
和 DOM 组件(例如 fieldset
)都不被视为此堆栈中的所有者,因为它们没有为包含 SubComponent
的节点 “creating” 做出贡献。App
和 DOM 组件仅转发了节点。App
仅渲染了 children
节点,而 Component
则通过 <SubComponent />
创建了一个包含 SubComponent
的节点。
¥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 />
.
Navigation
和 legend
都不在堆栈中,因为它只是包含 <SubComponent />
的节点的兄弟。
¥Neither Navigation
nor legend
are in the stack at all since it’s only a sibling to a node containing <SubComponent />
.
SubComponent
被省略,因为它已经是调用堆栈的一部分。
¥SubComponent
is omitted because it’s already part of the callstack.
用法
¥Usage
增强自定义错误覆盖
¥Enhance a custom error overlay
import { captureOwnerStack } from "react";
import { instrumentedConsoleError } from "./errorOverlay";
const originalConsoleError = console.error;
console.error = function patchedConsoleError(...args) {
originalConsoleError.apply(console, args);
const ownerStack = captureOwnerStack();
onConsoleError({
// Keep in mind that in a real application, console.error can be
// called with multiple arguments which you should account for.
consoleMessage: args[0],
ownerStack,
});
};
如果你拦截 console.error
调用以在错误叠加层中高亮它们,则可以调用 captureOwnerStack
来包含所有者堆栈。
¥If you intercept console.error
calls to highlight them in an error overlay, you can call captureOwnerStack
to include the Owner Stack.
import { captureOwnerStack } from "react"; import { createRoot } from "react-dom/client"; import App from './App'; import { onConsoleError } from "./errorOverlay"; import './styles.css'; const originalConsoleError = console.error; console.error = function patchedConsoleError(...args) { originalConsoleError.apply(console, args); const ownerStack = captureOwnerStack(); onConsoleError({ // Keep in mind that in a real application, console.error can be // called with multiple arguments which you should account for. consoleMessage: args[0], ownerStack, }); }; const container = document.getElementById("root"); createRoot(container).render(<App />);
故障排除
¥Troubleshooting
所有者堆栈为 null
¥The Owner Stack is null
captureOwnerStack
的调用发生在 React 控制函数之外,例如在 setTimeout
回调中、在 fetch
调用之后或在自定义 DOM 事件处理程序中。在渲染期间,效果、React 事件处理程序和 React 错误处理程序(例如 hydrateRoot#options.onCaughtError
)Owner Stacks 应该可用。
¥The call of captureOwnerStack
happened outside of a React controlled function e.g. in a setTimeout
callback, after a fetch
call or in a custom DOM event handler. During render, Effects, React event handlers, and React error handlers (e.g. hydrateRoot#options.onCaughtError
) Owner Stacks should be available.
在下面的例子中,单击按钮将记录一个空的 Owner Stack,因为 captureOwnerStack
是在自定义 DOM 事件处理程序期间调用的。必须更早地捕获所有者堆栈,例如通过将 captureOwnerStack
的调用移到副作用主体中。
¥In the example below, clicking the button will log an empty Owner Stack because captureOwnerStack
was called during a custom DOM event handler. The Owner Stack must be captured earlier e.g. by moving the call of captureOwnerStack
into the Effect body.
import {captureOwnerStack, useEffect} from 'react'; export default function App() { useEffect(() => { // Should call `captureOwnerStack` here. function handleEvent() { // Calling it in a custom DOM event handler is too late. // The Owner Stack will be `null` at this point. console.log('Owner Stack: ', captureOwnerStack()); } document.addEventListener('click', handleEvent); return () => { document.removeEventListener('click', handleEvent); } }) return <button>Click me to see that Owner Stacks are not available in custom DOM event handlers</button>; }
captureOwnerStack
不可用
¥captureOwnerStack
is not available
captureOwnerStack
仅在开发版本中导出。它将在生产版本中成为 undefined
。如果 captureOwnerStack
用于为生产和开发打包的文件中,则应有条件地从命名空间导入中访问它。
¥captureOwnerStack
is only exported in development builds. It will be undefined
in production builds. If captureOwnerStack
is used in files that are bundled for production and development, you should conditionally access it from a namespace import.
// Don't use named imports of `captureOwnerStack` in files that are bundled for development and production.
import {captureOwnerStack} from 'react';
// Use a namespace import instead and access `captureOwnerStack` conditionally.
import * as React from 'react';
if (process.env.NODE_ENV !== 'production') {
const ownerStack = React.captureOwnerStack();
console.log('Owner Stack', ownerStack);
}