熱模組替換
本頁面內容

熱模組替換

熱模組替換是一種在您的應用程式中更新模組的技術,而無需重新載入頁面。這是一種很棒的開發者體驗,當使用 Vite 時,React Router 支援它。

HMR 盡力在更新之間保留瀏覽器狀態。例如,假設您在模態視窗中填寫了一個表單,並填寫了所有欄位。當您儲存對程式碼的任何變更時,傳統的即時重新載入將會硬重新整理頁面,導致所有這些欄位都被重設。每次您進行變更時,您都必須再次打開模態視窗並再次填寫表單。

但是使用 HMR,所有這些狀態都會在更新之間被保留。

React Fast Refresh

React 已經有透過其 虛擬 DOM 更新 DOM 的機制,以回應使用者互動,例如點擊按鈕。如果 React 也能處理回應程式碼變更來更新 DOM,那不是很好嗎?

這正是 React Fast Refresh 的全部目的!當然,React 一切都關於元件,而不是一般的 JavaScript 程式碼,因此 React Fast Refresh 僅處理匯出的 React 元件的熱更新。

但是 React Fast Refresh 確實有一些您應該注意的限制。

類別元件狀態

React Fast Refresh 不會保留類別元件的狀態。這包括內部回傳類別的高階元件。

export class ComponentA extends Component {} // ❌

export const ComponentB = HOC(ComponentC); // ❌ Won't work if HOC returns a class component

export function ComponentD() {} // ✅
export const ComponentE = () => {}; // ✅
export default function ComponentF() {} // ✅

具名函式元件

函式元件必須是具名的,而不是匿名的,React Fast Refresh 才能追蹤變更。

export default () => {}; // ❌
export default function () {} // ❌

const ComponentA = () => {};
export default ComponentA; // ✅

export default function ComponentB() {} // ✅

支援的匯出

React Fast Refresh 只能處理元件匯出。雖然 React Router 為您管理路由匯出,例如 action headerslinksloadermeta,但任何使用者定義的匯出都會導致完整重新載入。

// These exports are handled by the React Router Vite plugin
// to be HMR-compatible
export const meta = { title: "Home" }; // ✅
export const links = [
  { rel: "stylesheet", href: "style.css" },
]; // ✅

// These exports are removed by the React Router Vite plugin
// so they never affect HMR
export const headers = { "Cache-Control": "max-age=3600" }; // ✅
export const loader = async () => {}; // ✅
export const action = async () => {}; // ✅

// This is not a route module export, nor a component export,
// so it will cause a full reload for this route
export const myValue = "some value"; // ❌

export default function Route() {} // ✅

👆 路由可能無論如何都不應該匯出像那樣的隨機值。如果您想在路由之間重複使用值,請將它們放在它們自己的非路由模組中。

export const myValue = "some value";

變更 Hooks

當 Hooks 被新增或從元件中移除時,React Fast Refresh 無法追蹤元件的變更,僅僅為了下一次渲染而導致完整重新載入。在 Hooks 更新後,變更應該再次導致熱更新。例如,如果您在元件中新增 useState,您可能會在下一次渲染中遺失該元件的本機狀態。

此外,如果您正在解構 Hook 的回傳值,如果移除或重新命名解構的鍵,React Fast Refresh 將無法為元件保留狀態。例如:

export default function Component({ loaderData }) {
  const { pet } = useMyCustomHook();
  return (
    <div>
      <input />
      <p>My dog's name is {pet.name}!</p>
    </div>
  );
}

如果您將鍵 pet 變更為 dog

 export default function Component() {
-  const { pet } = useMyCustomHook();
+  const { dog } = useMyCustomHook();
   return (
     <div>
       <input />
-      <p>My dog's name is {pet.name}!</p>
+      <p>My dog's name is {dog.name}!</p>
     </div>
   );
 }

那麼 React Fast Refresh 將無法保留狀態 <input /> ❌。

元件 Keys

在某些情況下,React 無法區分現有元件被變更和新增元件。 React 需要 key 來消除這些歧義,並在修改同層級元素時追蹤變更。

文件與範例 CC 4.0