react.devのご紹介

2023年3月16日、Dan Abramov氏とRachel Nabors氏による投稿


本日、Reactとそのドキュメントの新しいホームとなるreact.devをローンチしました。この投稿では、新しいサイトをご案内します。


要約

  • 新しいReactサイト(react.dev)では、関数コンポーネントとHooksを使用した最新のReactについて説明しています。
  • 図、イラスト、チャレンジ、そして600以上の新しいインタラクティブな例が含まれています。
  • 以前のReactドキュメントサイトは、legacy.reactjs.orgに移動しました。

新しいサイト、新しいドメイン、新しいホームページ

まずは、少し整理をしましょう。

新しいドキュメントの公開を記念し、そしてより重要なこととして、古いコンテンツと新しいコンテンツを明確に区別するために、より短いreact.devドメインに移行しました。古いreactjs.orgドメインは、こちらにリダイレクトされるようになります。

古いReactドキュメントは、legacy.reactjs.orgにアーカイブされました。「ウェブを壊す」ことを避けるため、既存の古いコンテンツへのリンクはすべて自動的にそこにリダイレクトされますが、レガシーサイトはこれ以上の更新はあまり行われません。

信じられないかもしれませんが、Reactはまもなく10歳になります。JavaScriptの世界では、それはまるまる一世紀のようなものです!私たちは、Reactのホームページを刷新し、Reactが今日ユーザーインターフェースを作成するための優れた方法であると考える理由を反映させ、入門ガイドを更新して、最新のReactベースのフレームワークをより明確に言及するようにしました。

まだ新しいホームページをご覧になっていない方は、ぜひご覧ください!

Hooksを使用した最新のReactへの全面的な移行

2018年にReact Hooksをリリースしたとき、Hooksのドキュメントは読者がクラスコンポーネントに精通していることを前提としていました。これはコミュニティがHooksを非常に迅速に採用するのに役立ちましたが、しばらくすると古いドキュメントは新しい読者に対応できなくなりました。新しい読者はReactを2回学習する必要がありました。1回はクラスコンポーネントで、もう1回はHooksでです。

新しいドキュメントでは、最初からHooksを使用してReactを学習します。ドキュメントは大きく2つのセクションに分かれています。

  • Reactを学ぶは、Reactをゼロから学ぶための自習型コースです。
  • APIリファレンスは、すべてのReact APIの詳細と使用例を提供します。

各セクションの内容を詳しく見ていきましょう。

注記

まだHooksベースの同等のものがない、クラスコンポーネントのまれなユースケースがいくつかあります。クラスコンポーネントは引き続きサポートされており、新しいサイトのレガシーAPIセクションに記載されています。

クイックスタート

学習セクションは、クイックスタートページから始まります。これは、Reactの簡単な入門ツアーです。コンポーネント、props、stateなどの概念の構文を紹介しますが、それらの使用方法については詳しく説明しません。

実践しながら学習したい場合は、次に三目並べチュートリアルをご覧ください。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を学ぶ機会を平等に持てるようにしたいと考えています。

そのため、「学習」セクションは、章ごとに分かれた自習形式のコースのように構成されています。最初の2つの章では、Reactの基礎について説明します。Reactを初めて使用する方、または記憶を新たにした方は、ここから始めてください。

次の2つの章は、より高度な内容で、Reactの難しい部分についてより深く理解することができます。

  • 状態の管理 では、アプリケーションが複雑になるにつれてロジックを整理する方法を学びます。
  • エスケープハッチ では、Reactの「外側」に stepping out する方法と、それが最も効果的な場合について学びます。

各章は、いくつかの関連ページで構成されています。これらのページのほとんどは、特定のスキルまたはテクニックを教えるものです。たとえば、JSXを使ったマークアップの記述状態のオブジェクトの更新、またはコンポーネント間での状態の共有などです。また、レンダリングとコミット状態のスナップショットなど、アイデアの説明に焦点を当てたページもあります。エフェクトは必要ないかもしれませんのように、これまでの経験に基づいた提案を共有するページもあります。

これらの章を順番に読む必要はありません。そんな時間のある人はいません!しかし、そうすることもできます。「学習」セクションのページは、前のページで紹介された概念のみに基づいています。本のように読みたい場合は、どうぞ!

チャレンジで理解度を確認する

「学習」セクションのほとんどのページは、理解度を確認するためのチャレンジで終わっています。たとえば、条件付きレンダリングのページにあるチャレンジをいくつか紹介します。

すぐに解く必要はありません!どうしてもやりたい場合を除いて。

チャレンジ 1/ 2:
未完了のアイテムのアイコンを? :で表示する

isPackedtrueでない場合、条件演算子(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>
  );
}

左下隅にある「解答を表示」ボタンに注目してください。 自分の解答を確認したい場合に便利です。

図とイラストで直感的に理解する

コードと単語だけでは説明できない場合、直感的に理解できる図を追加しました。たとえば、状態の保持とリセットの図の1つを紹介します。

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.

sectiondivに変更されると、sectionは削除され、新しいdivが追加されます。

ドキュメント全体にイラストも掲載されています。ブラウザが画面を描画する様子のイラストを1つ紹介します。

A browser painting 'still life with card element'.

イラストレーター: Rachel Lee Nabors

ブラウザベンダーに確認したところ、この描写は100%科学的に正確であることが確認されています。

新しくなった詳細なAPIリファレンス

APIリファレンスでは、すべてのReact APIに専用のページが設けられています。これには、あらゆる種類のAPIが含まれます。

  • useStateなどの組み込みフック。
  • <Suspense>などの組み込みコンポーネント。
  • <input> のような組み込みブラウザコンポーネントです。
  • renderToPipeableStream のようなフレームワーク指向の API です。
  • memo のようなその他の React API です。

すべての API ページは、少なくとも _リファレンス_ と _使用法_ の 2 つのセグメントに分かれていることがわかります。

_リファレンス_ は、引数と戻り値を列挙することで、正式な 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 McCabe、Sophie Alpert、Rick Hanlon、Andrew Clark、Matt Carroll には、執筆への追加の貢献に感謝します。また、Natalia Tepluhina と Sebastian Markbåge には、アイデアとフィードバックに感謝します。

サイトのデザインは Dan Lebowitz に、サンドボックスのデザインは Razvan Gradinar に感謝します。

開発面では、プロトタイプの開発にご尽力いただいたJared Palmer氏に感謝いたします。Dane Grant氏とDustin Goodman氏(ThisDotLabs所属)には、UI開発のサポートをいただき、感謝申し上げます。Ives van Hoorne氏、Alex Moldovan氏、Jasper De Moor氏、そしてDanilo Woznica氏(CodeSandbox所属)には、サンドボックス統合の作業に感謝いたします。Rick Hanlon氏には、スポット開発とデザイン作業、そして配色や細部の調整に感謝いたします。Harish Kumar氏とLuna Ruan氏には、サイトへの新機能の追加とメンテナンスにご尽力いただき、感謝申し上げます。

アルファ版とベータ版のテストプログラムにご参加いただいたボランティアの方々には、大変感謝しております。皆様の熱意と貴重なフィードバックは、このドキュメントを形作る上で大変役立ちました。特に、ベータテスターのDebbie O’Brien氏には、React Conf 2021でReactドキュメントの使用経験について講演いただいたことに、深く感謝いたします。

最後に、この取り組みのインスピレーションの源であるReactコミュニティに感謝いたします。皆様が私たちがこの活動を行う理由であり、新しいドキュメントがReactを使ってあらゆるユーザーインターフェースを構築する上で役立つことを願っています。

(前後の記事へのリンクは日本語で適切な表現に置き換える必要があります)