除錯 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 會擲出此錯誤。造成此錯誤的常見原因是將 default
和 named
匯出混淆在一起。
// 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" />
無效的事件處理常式
有時你可能會意外地將錯誤值傳遞給事件處理常式。如果你要移除事件處理常式,它們必須永遠是 function
或 null
。所有其他類型都是無效的。
// 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.x | Preact 10.x |
---|---|
vnode.nodeName | vnode.type |
vnode.attributes | vnode.props |
vnode.children | vnode.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>