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,onRecoverableErrorvà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.
captureOwnerStacksẽ luôn trả vềnullbê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 AppTuy nhiên, Owner Stack sẽ chỉ đọc
at ComponentCả 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);
}