介绍 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入门教程。它介绍了组件、props和状态等概念的语法,但并没有详细介绍如何使用它们。

如果您喜欢通过实践学习,我们建议您接下来查看 井字游戏教程。它指导您使用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新手,或者想刷新一下您的记忆,请从这里开始

  • UI描述 教你如何使用组件显示信息。
  • 添加交互性 教你如何响应用户输入来更新屏幕。

接下来的两章内容更高级,将带你深入了解一些更棘手的部分。

  • 状态管理 教你如何在应用复杂度增加时组织你的逻辑。
  • 逃生舱 教你如何“跳出”React,以及何时这样做最合理。

每一章都包含几个相关的页面。大多数页面讲解特定的技能或技巧——例如,使用JSX编写标记更新状态中的对象,或在组件之间共享状态。有些页面侧重于解释一个概念——例如渲染和提交,或状态快照。还有一些页面,例如你可能不需要一个effect,分享了我们多年来积累的经验建议。

你不必按顺序阅读这些章节。谁有时间这么做?!但你可以这么做。学习部分的页面只依赖于前面页面介绍的概念。如果你想像读一本书一样阅读,那就开始吧!

通过挑战来检验你的理解

学习部分的大多数页面最后都有一些挑战来检验你的理解。例如,这里有一些关于条件渲染页面的挑战。

你现在不必解决它们!除非你真的想。

挑战 1 2:
使用图标显示未完成的项目 ? :

使用条件运算符 (cond ? a : b) 在 isPacked 不是 true 时渲染一个 ❌。

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

你还会在文档中看到一些插图——这是浏览器绘制屏幕中的一个。

绘制。我们已与浏览器厂商确认,此图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,她在 React Conf 2021 上分享了她使用 React 文档的经验。

最后,感谢 React 社区,正是你们的灵感促成了这项工作。你们是我们的动力,我们希望新的文档能够帮助你们使用 React 构建任何想要的用户界面。