captureOwnerStack
captureOwnerStack
đọc Owner Stack hiện tại trong quá trình phát triển và trả về nó dưới dạng một chuỗi nếu có.
const stack = captureOwnerStack();
Tham khảo
captureOwnerStack()
Gọi captureOwnerStack
để lấy Owner Stack hiện tại.
import * as React from 'react';
function Component() {
if (process.env.NODE_ENV !== 'production') {
const ownerStack = React.captureOwnerStack();
console.log(ownerStack);
}
}
Tham số
captureOwnerStack
không nhận bất kỳ tham số nào.
Giá trị trả về
captureOwnerStack
trả về string | null
.
Owner Stack có sẵn trong
- Quá trình render Component
- Các Effect (ví dụ:
useEffect
) - Các trình xử lý sự kiện của React (ví dụ:
<button onClick={...} />
) - Các trình xử lý lỗi của React (Tùy chọn React Root
onCaughtError
,onRecoverableError
vàonUncaughtError
)
Nếu không có Owner Stack nào khả dụng, null
sẽ được trả về (xem Khắc phục sự cố: Owner Stack là null
).
Lưu ý
- Owner Stack chỉ khả dụng trong quá trình phát triển.
captureOwnerStack
sẽ luôn trả vềnull
bên ngoài quá trình phát triển.
Tìm hiểu sâu
Owner Stack khác với Component Stack có sẵn trong các trình xử lý lỗi của React như errorInfo.componentStack
trong onUncaughtError
.
Ví dụ: xem xét đoạn mã sau:
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) => { // Các stack được ghi lại thay vì hiển thị chúng trực tiếp trong UI để // làm nổi bật rằng các trình duyệt sẽ áp dụng sourcemap cho các stack đã ghi lại. // Lưu ý rằng sourcemapping chỉ được áp dụng trong bảng điều khiển trình duyệt thực chứ không // trong bảng điều khiển giả được hiển thị trên trang này. // Nhấn "fork" để có thể xem stack đã được sourcemap trong một bảng điều khiển thực. console.log(errorInfo.componentStack); console.log(captureOwnerStack()); }, }).render( <App> <Component label="disabled" /> </App> );
SubComponent
sẽ ném ra một lỗi.
Component Stack của lỗi đó sẽ là
at SubComponent
at fieldset
at Component
at main
at React.Suspense
at App
Tuy nhiên, Owner Stack sẽ chỉ đọc
at Component
Cả App
và các component DOM (ví dụ: fieldset
) đều không được coi là Owner trong Stack này vì chúng không đóng góp vào việc “tạo” node chứa SubComponent
. App
và các component DOM chỉ chuyển tiếp node. App
chỉ render node children
trái ngược với Component
, component này đã tạo một node chứa SubComponent
thông qua <SubComponent />
.
Cả Navigation
và legend
đều không có trong stack vì nó chỉ là một sibling của một node chứa <SubComponent />
.
SubComponent
bị bỏ qua vì nó đã là một phần của callstack.
Cách sử dụng
Cải thiện lớp phủ lỗi tùy chỉnh
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({
// Lưu ý rằng trong một ứng dụng thực tế, console.error có thể được
// gọi với nhiều đối số mà bạn nên tính đến.
consoleMessage: args[0],
ownerStack,
});
};
Nếu bạn chặn các lệnh gọi console.error
để làm nổi bật chúng trong lớp phủ lỗi, bạn có thể gọi captureOwnerStack
để bao gồm 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({ // Lưu ý rằng trong một ứng dụng thực tế, console.error có thể được // gọi với nhiều đối số mà bạn nên tính đến. consoleMessage: args[0], ownerStack, }); }; const container = document.getElementById("root"); createRoot(container).render(<App />);
Khắc phục sự cố
Owner Stack là null
Lệnh gọi captureOwnerStack
xảy ra bên ngoài một hàm được kiểm soát bởi React, ví dụ: trong một callback setTimeout
, sau một lệnh gọi fetch
hoặc trong một trình xử lý sự kiện DOM tùy chỉnh. Trong quá trình render, Effects, trình xử lý sự kiện React và trình xử lý lỗi React (ví dụ: hydrateRoot#options.onCaughtError
), Owner Stack sẽ khả dụng.
Trong ví dụ dưới đây, việc nhấp vào nút sẽ ghi lại một Owner Stack trống vì captureOwnerStack
đã được gọi trong một trình xử lý sự kiện DOM tùy chỉnh. Owner Stack phải được chụp sớm hơn, ví dụ: bằng cách di chuyển lệnh gọi captureOwnerStack
vào phần thân Effect.
import {captureOwnerStack, useEffect} from 'react'; export default function App() { useEffect(() => { // Nên gọi `captureOwnerStack` ở đây. function handleEvent() { // Gọi nó trong một trình xử lý sự kiện DOM tùy chỉnh là quá muộn. // Owner Stack sẽ là `null` tại thời điểm này. console.log('Owner Stack: ', captureOwnerStack()); } document.addEventListener('click', handleEvent); return () => { document.removeEventListener('click', handleEvent); } }) return <button>Nhấp vào tôi để thấy rằng Owner Stack không khả dụng trong trình xử lý sự kiện DOM tùy chỉnh</button>; }
captureOwnerStack
không khả dụng
captureOwnerStack
chỉ được xuất trong các bản dựng dành cho quá trình phát triển. Nó sẽ là undefined
trong các bản dựng production. Nếu captureOwnerStack
được sử dụng trong các tệp được đóng gói cho cả production và development, bạn nên truy cập có điều kiện từ một namespace import.
// Không sử dụng named import của `captureOwnerStack` trong các tệp được đóng gói cho development và production.
import {captureOwnerStack} from 'react';
// Sử dụng namespace import thay thế và truy cập `captureOwnerStack` có điều kiện.
import * as React from 'react';
if (process.env.NODE_ENV !== 'production') {
const ownerStack = React.captureOwnerStack();
console.log('Owner Stack', ownerStack);
}