說明
支持我們

除錯 Preact 應用程式

Preact 附帶許多工具,可讓除錯更輕鬆。這些工具會封裝在單一匯入中,可透過匯入 preact/debug 納入。

這些工具包括與我們自己的 Preact Devtools 擴充功能整合,適用於 Chrome 和 Firefox。

當我們偵測到錯誤,例如 <table> 元素中嵌套不正確時,我們會列印警告或錯誤。



安裝

Preact Devtools 可安裝在瀏覽器的擴充功能商店中。

安裝後,我們需要在某處匯入 preact/debug 以初始化與擴充功能的連線。請確定此匯入是整個應用程式中的第一個匯入。

preact-cli 會自動包含 preact/debug 套件。如果您使用它,可以安全地略過下一步!

以下是應用程式主入口檔案的範例。

// Must be the first import
import "preact/debug";
import { render } from 'preact';
import App from './components/App';

render(<App />, document.getElementById('root'));

移除生產環境中的開發人員工具

大多數套件管理工具允許您在偵測到 if 陳述式中的分支永遠不會被觸發時移除程式碼。我們可以使用此功能在開發期間僅包含 preact/debug,並在生產環境建置中節省這些寶貴的位元組。

// Must be the first import
if (process.env.NODE_ENV==='development') {
  // Must use require here as import statements are only allowed
  // to exist at top-level.
  require("preact/debug");
}

import { render } from 'preact';
import App from './components/App';

render(<App />, document.getElementById('root'));

請務必在建置工具中將 NODE_ENV 變數設定為正確的值。

除錯警告和錯誤

有時當 Preact 偵測到無效程式碼時,您可能會收到警告或錯誤。應修正這些問題以確保您的應用程式完美運作。

undefined 父項傳遞至 render()

這表示程式碼嘗試將您的應用程式呈現在空白處,而不是 DOM 節點中。兩者之間的差異如下:

// What Preact received
render(<App />, undefined);

// vs what it expected
render(<App />, actualDomNode);

發生此錯誤的主要原因是,在呼叫 render() 函式時,DOM 節點不存在。請確定它存在。

傳遞 undefined 元件至 createElement()

當你傳遞 undefined 而不是元件時,Preact 會擲出此錯誤。造成此錯誤的常見原因是將 defaultnamed 匯出混淆在一起。

// app.js
export default function App() {
  return <div>Hello World</div>;
}

// index.js: Wrong, because `app.js` doesn't have a named export
import { App } from './app';
render(<App />, dom);

當情況相反時,也會擲出相同的錯誤。當你宣告 named 匯出並嘗試將其用作 default 匯出時。檢查此問題的一個快速方法(如果你的編輯器尚未執行此操作),就是記錄匯入

// app.js
export function App() {
  return <div>Hello World</div>;
}

// index.js
import App from './app';

console.log(App);
// Logs: { default: [Function] } instead of the component

將 JSX 文字字面值傳遞為 JSX 兩次

再次將 JSX 文字字面值或元件傳遞到 JSX 中是無效的,並且會觸發此錯誤。

const Foo = <div>foo</div>;
// Invalid: Foo already contains a JSX-Element
render(<Foo />, dom);

若要修復此問題,我們可以直接傳遞變數

const Foo = <div>foo</div>;
render(Foo, dom);

偵測到表格巢狀不當

HTML 對於表格的結構方式有非常明確的指示。偏離此指示將導致難以偵錯的渲染錯誤。在 Preact 中,我們會偵測此問題並印出錯誤。若要深入了解表格的結構方式,我們強烈建議參閱 mdn 文件

無效的 ref 屬性

ref 屬性包含意外內容時,我們會擲出此錯誤。這包括已於一段時間前已棄用的基於字串的 ref

// valid
<div ref={e => {/* ... */)}} />

// valid
const ref = createRef();
<div ref={ref} />

// Invalid
<div ref="ref" />

無效的事件處理常式

有時你可能會意外地將錯誤值傳遞給事件處理常式。如果你要移除事件處理常式,它們必須永遠是 functionnull。所有其他類型都是無效的。

// valid
<div onClick={() => console.log("click")} />

// invalid
<div onClick={console.log("click")} />

掛勾只能從渲染方法呼叫

當您嘗試在組件外部使用勾子時,會發生此錯誤。它們僅支援在函數組件內部使用。

// Invalid, must be used inside a component
const [value, setValue] = useState(0);

// valid
function Foo() {
  const [value, setValue] = useState(0);
  return <button onClick={() => setValue(value + 1)}>{value}</button>;
}

取得 vnode.[property] 已過時

在 Preact X 中,我們對內部 vnode 形狀進行了一些重大變更。

Preact 8.xPreact 10.x
vnode.nodeNamevnode.type
vnode.attributesvnode.props
vnode.childrenvnode.props.children

找到具有相同金鑰的子項

基於 virtual-dom 的函式庫的一個獨特面向是,它們必須偵測子項何時被移動。然而,要了解哪個子項是什麼,我們需要以某種方式標記它們。這僅在您動態建立子項時需要。

// Both children will have the same key "A"
<div>
  {['A', 'A'].map(char => <p key={char}>{char}</p>)}
</div>

正確的做法是給予它們唯一的金鑰。在多數情況下,您正在迭代的資料將具有某種形式的 id

const persons = [
  { name: 'John', age: 22 },
  { name: 'Sarah', age: 24}
];

// Somewhere later in your component
<div>
  {persons.map(({ name, age }) => {
    return <p key={name}>{name}, Age: {age}</p>;
  })}
</div>