介紹 react.dev

2023 年 3 月 16 日,由 Dan AbramovRachel Nabors 發佈


今天,我們很高興推出 react.dev,這是 React 及其文件的新家。在這篇文章中,我們將帶您瀏覽這個新網站。


tl;dr (太長;沒讀)

  • 新的 React 網站 (react.dev) 使用函式元件和 Hooks 來教授現代 React。
  • 我們加入了圖表、插圖、挑戰和超過 600 個新的互動式範例。
  • 之前的 React 文件網站已移至 legacy.reactjs.org

新網站、新網域、新首頁

首先,一些注意事項。

為了慶祝新文件的推出,更重要的是,為了清楚地區分新舊內容,我們已改用較短的 react.dev 網域。舊的 reactjs.org 網域現在將會重新導向到這裡。

舊的 React 文件現在已封存於 legacy.reactjs.org。所有指向舊內容的現有連結都將自動重新導向到那裡,以避免「破壞網路」,但舊版網站將不會再有太多更新。

信不信由你,React 很快就要十歲了。以 JavaScript 的年齡來說,就像一個世紀!我們已更新 React 首頁,以反映我們認為 React 是現今建立使用者介面的絕佳方式的原因,並更新了入門指南,以更突出地提及基於現代 React 的框架。

如果您還沒有看過新的首頁,請去看看!

全力投入使用 Hooks 的現代 React

當我們在 2018 年發佈 React Hooks 時,Hooks 文件假設讀者熟悉類別元件。這有助於社群快速採用 Hooks,但在一段時間後,舊文件無法滿足新讀者的需求。新讀者必須學習 React 兩次:一次使用類別元件,然後再次使用 Hooks。

新文件從一開始就使用 Hooks 來教授 React。 文件分為兩個主要部分

  • 學習 React 是一個自定進度的課程,從零開始教授 React。
  • API 參考 提供每個 React API 的詳細資訊和用法範例。

讓我們仔細看看您可以在每個部分找到什麼。

備註

仍然有一些罕見的類別元件用例尚沒有基於 Hook 的等效項。類別元件仍然受支援,並記錄在新網站的 舊版 API 部分。

快速入門

「學習」部分以 快速入門 頁面開始。這是 React 的簡短介紹性導覽。它介紹了元件、屬性和狀態等概念的語法,但沒有詳細說明如何使用它們。

如果您喜歡透過實作來學習,我們建議您接下來查看 井字遊戲教學。它會引導您使用 React 建立一個小遊戲,同時教授您每天都會使用的技能。以下是您將建構的內容

import { useState } from 'react';

function Square({ value, onSquareClick }) {
  return (
    <button className="square" onClick={onSquareClick}>
      {value}
    </button>
  );
}

function Board({ xIsNext, squares, onPlay }) {
  function handleClick(i) {
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = 'X';
    } else {
      nextSquares[i] = 'O';
    }
    onPlay(nextSquares);
  }

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = 'Winner: ' + winner;
  } else {
    status = 'Next player: ' + (xIsNext ? 'X' : 'O');
  }

  return (
    <>
      <div className="status">{status}</div>
      <div className="board-row">
        <Square value={squares[0]} onSquareClick={() => handleClick(0)} />
        <Square value={squares[1]} onSquareClick={() => handleClick(1)} />
        <Square value={squares[2]} onSquareClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onSquareClick={() => handleClick(3)} />
        <Square value={squares[4]} onSquareClick={() => handleClick(4)} />
        <Square value={squares[5]} onSquareClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onSquareClick={() => handleClick(6)} />
        <Square value={squares[7]} onSquareClick={() => handleClick(7)} />
        <Square value={squares[8]} onSquareClick={() => handleClick(8)} />
      </div>
    </>
  );
}

export default function Game() {
  const [history, setHistory] = useState([Array(9).fill(null)]);
  const [currentMove, setCurrentMove] = useState(0);
  const xIsNext = currentMove % 2 === 0;
  const currentSquares = history[currentMove];

  function handlePlay(nextSquares) {
    const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
    setHistory(nextHistory);
    setCurrentMove(nextHistory.length - 1);
  }

  function jumpTo(nextMove) {
    setCurrentMove(nextMove);
  }

  const moves = history.map((squares, move) => {
    let description;
    if (move > 0) {
      description = 'Go to move #' + move;
    } else {
      description = 'Go to game start';
    }
    return (
      <li key={move}>
        <button onClick={() => jumpTo(move)}>{description}</button>
      </li>
    );
  });

  return (
    <div className="game">
      <div className="game-board">
        <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
      </div>
      <div className="game-info">
        <ol>{moves}</ol>
      </div>
    </div>
  );
}

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

我們也想重點介紹 React 思維 - 這是讓許多人「理解」React 的教學。 我們已將這兩個經典教學更新為使用函式元件和 Hooks,因此它們煥然一新。

備註

上面的範例是一個*沙盒*。我們在整個網站中添加了很多沙盒 - 超過 600 個!您可以編輯任何沙盒,或按下右上角的「分支」將其在新分頁中開啟。沙盒可讓您快速使用 React API、探索您的想法並檢查您的理解。

逐步學習 React

我們希望世界上每個人都有平等的機會免費自學 React。

這就是為什麼「學習」區段的組織方式像是一個自學課程,並分成幾個章節。前兩個章節描述了 React 的基礎知識。如果您是 React 新手,或者想要複習一下,請從這裡開始。

接下來的兩個章節更進階,將讓您更深入地了解比較棘手的部分。

  • 管理狀態 教您如何在應用程式變得複雜時組織您的邏輯。
  • 逃生出口 教您如何在必要時「跳出」React。

每個章節都包含幾個相關的頁面。大多數頁面教授特定的技能或技巧,例如 使用 JSX 編寫標記更新狀態中的物件在元件之間共享狀態。有些頁面著重於解釋一個概念,例如 渲染和提交狀態作為快照。還有一些頁面,例如 您可能不需要 Effect,會根據我們這些年來學到的知識分享我們的建議。

您不必按順序閱讀這些章節。誰有時間這樣做?!但您可以這樣做。學習區段中的頁面僅依賴先前頁面介紹的概念。如果您想像閱讀一本書一樣閱讀它,那就去吧!

透過挑戰來檢驗您的理解程度

學習區段中的大多數頁面都以一些挑戰作為結尾,以檢驗您的理解程度。例如,以下是關於 條件渲染 頁面的一些挑戰。

您不必現在就解決它們!除非您 *真的* 想這樣做。

挑戰 1 2:
使用 ? : 顯示未完成項目的圖示

如果 isPacked 不是 true,請使用條件運算子 (cond ? a : b) 來渲染 ❌。

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✅'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

請注意左下角的「顯示解答」按鈕。如果您想檢查自己的答案,它會很方便!

利用圖表和插圖建立直覺

當我們無法單獨使用程式碼和文字來解釋某些內容時,我們新增了一些圖表來幫助提供一些直覺。例如,以下是 保留和重設狀態 中的其中一個圖表。

Diagram with three sections, with an arrow transitioning each section in between. The first section contains a React component labeled 'div' with a single child labeled 'section', which has a single child labeled 'Counter' containing a state bubble labeled 'count' with value 3. The middle section has the same 'div' parent, but the child components have now been deleted, indicated by a yellow 'proof' image. The third section has the same 'div' parent again, now with a new child labeled 'div', highlighted in yellow, also with a new child labeled 'Counter' containing a state bubble labeled 'count' with value 0, all highlighted in yellow.
Diagram with three sections, with an arrow transitioning each section in between. The first section contains a React component labeled 'div' with a single child labeled 'section', which has a single child labeled 'Counter' containing a state bubble labeled 'count' with value 3. The middle section has the same 'div' parent, but the child components have now been deleted, indicated by a yellow 'proof' image. The third section has the same 'div' parent again, now with a new child labeled 'div', highlighted in yellow, also with a new child labeled 'Counter' containing a state bubble labeled 'count' with value 0, all highlighted in yellow.

section 改變為 div 時,section 會被刪除,並新增新的 div

您還會在整個文件中看到一些插圖——以下是 瀏覽器繪製螢幕 的其中一個插圖。

A browser painting 'still life with card element'.

插圖作者: Rachel Lee Nabors

我們已與瀏覽器廠商確認,此圖示 100% 科學準確。

新的、詳細的 API 參考

API 參考 中,每個 React API 現在都有專屬的頁面。這包括所有種類的 API:

您會注意到每個 API 頁面都至少分為兩個部分:*參考* 和 *用法*。

參考」透過列出參數和回傳值來描述正式的 API 簽章。它很簡潔,但如果您不熟悉該 API,可能會覺得有點抽象。它描述了 API 的功能,但沒有說明如何使用它。

用法」展示了您在實務中為何以及如何使用此 API,就像同事或朋友可能會解釋的那樣。它展示了 React 團隊預期每個 API 使用的典型情境。 我們添加了顏色標記的程式碼片段、不同 API 一起使用的範例,以及您可以複製貼上的程式碼範本。

useState 基本範例

範例 1 4:
計數器(數字)

在此範例中,狀態變數 count 包含一個數字。點擊按鈕會將其遞增。

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}

某些 API 頁面還包含「疑難排解」(針對常見問題)和「替代方案」(針對已棄用的 API)。

我們希望這種方法不僅可以讓 API 參考成為查詢參數的方式,還可以讓您了解任何給定 API 的所有不同用法,以及它與其他 API 的關聯。

接下來呢?

我們的小旅程到此結束! 瀏覽新的網站,看看您喜歡或不喜歡什麼,並在我們的 問題追蹤器 中提供您的意見回饋。

我們承認這個專案花了很長時間才推出。我們希望維持 React 社群應得的高品質標準。在撰寫這些文件和建立所有範例的過程中,我們在自己的說明、React 中的錯誤,甚至 React 設計中的缺失中發現了一些錯誤,我們現在正在努力解決這些問題。我們希望新的文件能幫助我們在未來將 React 本身提升到更高的標準。

我們聽到了您許多關於擴展網站內容和功能的要求,例如:

  • 為所有範例提供 TypeScript 版本;
  • 建立更新的效能、測試和輔助使用指南;
  • 獨立於支援 React 伺服器元件的框架來記錄它們;
  • 與我們的國際社群合作,將新的文件翻譯成各種語言;
  • 為新網站新增缺少的功能(例如,此部落格的 RSS)。

現在 react.dev 已經推出,我們將能夠把重點從「追趕」第三方 React 教育資源轉移到新增資訊和進一步改進我們的新網站。

我們認為現在是學習 React 的最佳時機。

誰參與了這個專案?

在 React 團隊中,Rachel Nabors 領導了這個專案(並提供了插圖),而 Dan Abramov 設計了課程。他們也共同撰寫了大部分的內容。

當然,沒有這麼大的專案是單獨完成的。我們要感謝很多人!

Sylwia Vargas 全面修改了我們的範例,使其超越「foo/bar/baz」和小貓,並以來自世界各地的科學家、藝術家和城市為特色。Maggie Appleton 將我們的塗鴉變成了一個清晰的圖表系統。

感謝 David McCabeSophie AlpertRick HanlonAndrew ClarkMatt Carroll 額外撰寫的貢獻。我們也要感謝 Natalia TepluhinaSebastian Markbåge 的想法和回饋。

感謝 Dan Lebowitz 的網站設計和 Razvan Gradinar 的沙盒設計。

在開發方面,感謝 Jared Palmer 進行原型開發。感謝來自 ThisDotLabsDane GrantDustin Goodman 對 UI 開發的支持。感謝來自 CodeSandboxIves van HoorneAlex MoldovanJasper De MoorDanilo Woznica 他們在沙盒整合方面的工作。感謝 Rick Hanlon 在局部開發和設計工作上的貢獻,完善了我們的色彩和細節。感謝 Harish KumarLuna Ruan 為網站添加新功能並協助維護。

非常感謝自願參與 Alpha 和 Beta 測試計劃的人們。您的熱情和寶貴的意見幫助我們塑造了這些文件。特別感謝我們的 Beta 測試員 Debbie O’Brien,她在 2021 年 React Conf 上發表了關於她使用 React 文件的經驗的演講。

最後,感謝 React 社群成為這項努力背後的靈感來源。你們是我們這樣做的原因,我們希望新的文件能幫助您使用 React 建立任何您想要的使用者介面。

... (保留原文 HTML 程式碼,因翻譯意義不大)