快速开始

欢迎使用 React 文档!本页将向你介绍你每天会用到的 80% 的 React 概念。

¥Welcome to the React documentation! This page will give you an introduction to the 80% of React concepts that you will use on a daily basis.

你将学习到

  • 如何创建和嵌套组件

    ¥How to create and nest components

  • 如何添加标记和样式

    ¥How to add markup and styles

  • 如何显示数据

    ¥How to display data

  • 如何渲染条件和列表

    ¥How to render conditions and lists

  • 如何响应事件和更新屏幕

    ¥How to respond to events and update the screen

  • 如何在组件之间共享数据

    ¥How to share data between components

创建和嵌套组件

¥Creating and nesting components

React 应用由组件组成。组件是 UI(用户界面)的一部分,具有自己的逻辑和外观。组件可以小到一个按钮,也可以大到整个页面。

¥React apps are made out of components. A component is a piece of the UI (user interface) that has its own logic and appearance. A component can be as small as a button, or as large as an entire page.

React 组件是返回标记的 JavaScript 函数:

¥React components are JavaScript functions that return markup:

function MyButton() {
return (
<button>I'm a button</button>
);
}

现在你已经声明了 MyButton,你可以将它嵌套到另一个组件中:

¥Now that you’ve declared MyButton, you can nest it into another component:

export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}

请注意,<MyButton /> 以大写字母开头。这就是你知道它是 React 组件的方式。React 组件名称必须始终以大写字母开头,而 HTML 标签必须是小写字母。

¥Notice that <MyButton /> starts with a capital letter. That’s how you know it’s a React component. React component names must always start with a capital letter, while HTML tags must be lowercase.

看看结果:

¥Have a look at the result:

function MyButton() {
  return (
    <button>
      I'm a button
    </button>
  );
}

export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <MyButton />
    </div>
  );
}

export default 关键字指定文件中的主要组件。如果你不熟悉某些 JavaScript 语法,MDNjavascript.info 有很好的参考资料。

¥The export default keywords specify the main component in the file. If you’re not familiar with some piece of JavaScript syntax, MDN and javascript.info have great references.

使用 JSX 编写标记

¥Writing markup with JSX

你在上面看到的标记语法称为 JSX。它是可选的,但大多数 React 项目为了方便起见都使用 JSX。所有 我们推荐用于本地开发的工具 都支持开箱即用的 JSX。

¥The markup syntax you’ve seen above is called JSX. It is optional, but most React projects use JSX for its convenience. All of the tools we recommend for local development support JSX out of the box.

JSX 比 HTML 更严格。你必须闭合像 <br /> 这样的标签。你的组件也不能返回多个 JSX 标签。你必须将它们封装到共享的父级中,例如 <div>...</div> 或空的 <>...</> 封装器:

¥JSX is stricter than HTML. You have to close tags like <br />. Your component also can’t return multiple JSX tags. You have to wrap them into a shared parent, like a <div>...</div> or an empty <>...</> wrapper:

function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}

如果你有很多 HTML 要移植到 JSX,你可以使用 在线转换器

¥If you have a lot of HTML to port to JSX, you can use an online converter.

添加样式

¥Adding styles

在 React 中,你使用 className 指定一个 CSS 类。它的工作方式与 HTML class 属性相同:

¥In React, you specify a CSS class with className. It works the same way as the HTML class attribute:

<img className="avatar" />

然后在单独的 CSS 文件中为其编写 CSS 规则:

¥Then you write the CSS rules for it in a separate CSS file:

/* In your CSS */
.avatar {
border-radius: 50%;
}

React 没有规定你如何添加 CSS 文件。在最简单的情况下,你将向 HTML 添加 <link> 标记。如果你使用构建工具或框架,请查阅其文档以了解如何将 CSS 文件添加到你的项目中。

¥React does not prescribe how you add CSS files. In the simplest case, you’ll add a <link> tag to your HTML. If you use a build tool or a framework, consult its documentation to learn how to add a CSS file to your project.

显示数据

¥Displaying data

JSX 允许你将标记放入 JavaScript。大括号让你 “转义回” 到 JavaScript 中,这样你就可以从你的代码中嵌入一些变量并将它显示给用户。例如,这将显示 user.name

¥JSX lets you put markup into JavaScript. Curly braces let you “escape back” into JavaScript so that you can embed some variable from your code and display it to the user. For example, this will display user.name:

return (
<h1>
{user.name}
</h1>
);

你也可以使用 JSX 属性中的 “转义到 JavaScript”,但你必须使用大括号而不是引号。例如,className="avatar""avatar" 字符串作为 CSS 类传递,但 src={user.imageUrl} 读取 JavaScript user.imageUrl 变量值,然后将该值作为 src 属性传递:

¥You can also “escape into JavaScript” from JSX attributes, but you have to use curly braces instead of quotes. For example, className="avatar" passes the "avatar" string as the CSS class, but src={user.imageUrl} reads the JavaScript user.imageUrl variable value, and then passes that value as the src attribute:

return (
<img
className="avatar"
src={user.imageUrl}
/>
);

你也可以在 JSX 大括号内放置更复杂的表达式,例如 字符串连接

¥You can put more complex expressions inside the JSX curly braces too, for example, string concatenation:

const user = {
  name: 'Hedy Lamarr',
  imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
  imageSize: 90,
};

export default function Profile() {
  return (
    <>
      <h1>{user.name}</h1>
      <img
        className="avatar"
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  );
}

在上面的示例中,style={{}} 不是特殊语法,而是 style={ } JSX 大括号内的常规 {} 对象。当你的样式依赖于 JavaScript 变量时,你可以使用 style 属性。

¥In the above example, style={{}} is not a special syntax, but a regular {} object inside the style={ } JSX curly braces. You can use the style attribute when your styles depend on JavaScript variables.

条件渲染

¥Conditional rendering

在 React 中,没有用于编写条件的特殊语法。而是,你将使用与编写常规 JavaScript 代码时相同的技术。例如,你可以使用 if 语句有条件地包含 JSX:

¥In React, there is no special syntax for writing conditions. Instead, you’ll use the same techniques as you use when writing regular JavaScript code. For example, you can use an if statement to conditionally include JSX:

let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);

如果你喜欢更紧凑的代码,你可以使用 条件 ? 运算符。与 if 不同,它在 JSX 内部工作:

¥If you prefer more compact code, you can use the conditional ? operator. Unlike if, it works inside JSX:

<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>

当你不需要 else 分支时,你也可以使用更短的 逻辑 && 语法

¥When you don’t need the else branch, you can also use a shorter logical && syntax:

<div>
{isLoggedIn && <AdminPanel />}
</div>

所有这些方法也适用于有条件地指定属性。如果你不熟悉此 JavaScript 语法的某些部分,可以从始终使用 if...else 开始。

¥All of these approaches also work for conditionally specifying attributes. If you’re unfamiliar with some of this JavaScript syntax, you can start by always using if...else.

渲染列表

¥Rendering lists

你将依赖 for 循环数组 map() 函数 等 JavaScript 功能来渲染组件列表。

¥You will rely on JavaScript features like for loop and the array map() function to render lists of components.

例如,假设你有一系列产品:

¥For example, let’s say you have an array of products:

const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];

在你的组件内,使用 map() 函数将产品数组转换为 <li> 条目数组:

¥Inside your component, use the map() function to transform an array of products into an array of <li> items:

const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);

return (
<ul>{listItems}</ul>
);

请注意 <li> 如何具有 key 属性。对于列表中的每个条目,你应该传递一个字符串或数字,以在其兄弟项中唯一标识该条目。通常,键应该来自你的数据,例如数据库 ID。如果你稍后插入、删除或重新排序条目,React 使用你的键来了解发生了什么。

¥Notice how <li> has a key attribute. For each item in a list, you should pass a string or a number that uniquely identifies that item among its siblings. Usually, a key should be coming from your data, such as a database ID. React uses your keys to know what happened if you later insert, delete, or reorder the items.

const products = [
  { title: 'Cabbage', isFruit: false, id: 1 },
  { title: 'Garlic', isFruit: false, id: 2 },
  { title: 'Apple', isFruit: true, id: 3 },
];

export default function ShoppingList() {
  const listItems = products.map(product =>
    <li
      key={product.id}
      style={{
        color: product.isFruit ? 'magenta' : 'darkgreen'
      }}
    >
      {product.title}
    </li>
  );

  return (
    <ul>{listItems}</ul>
  );
}

响应事件

¥Responding to events

你可以通过在组件内声明事件处理函数来响应事件:

¥You can respond to events by declaring event handler functions inside your components:

function MyButton() {
function handleClick() {
alert('You clicked me!');
}

return (
<button onClick={handleClick}>
Click me
</button>
);
}

请注意 onClick={handleClick} 末尾没有括号!不要调用事件处理函数:你只需要传递下去。当用户单击按钮时,React 将调用你的事件处理程序。

¥Notice how onClick={handleClick} has no parentheses at the end! Do not call the event handler function: you only need to pass it down. React will call your event handler when the user clicks the button.

更新屏幕

¥Updating the screen

通常,你会希望你的组件 “记住” 一些信息并显示它。例如,你可能想要计算单击按钮的次数。为此,请将状态添加到你的组件。

¥Often, you’ll want your component to “remember” some information and display it. For example, maybe you want to count the number of times a button is clicked. To do this, add state to your component.

首先,从 React 导入 useState

¥First, import useState from React:

import { useState } from 'react';

现在你可以在你的组件中声明一个状态变量:

¥Now you can declare a state variable inside your component:

function MyButton() {
const [count, setCount] = useState(0);
// ...

你会从 useState 获得两个东西:当前状态 (count),以及让你更新它的函数 (setCount)。你可以给它们起任何名字,但惯例是写 [something, setSomething]

¥You’ll get two things from useState: the current state (count), and the function that lets you update it (setCount). You can give them any names, but the convention is to write [something, setSomething].

第一次显示按钮时,count 将是 0,因为你将 0 传递给了 useState()。当你想改变状态时,调用 setCount() 并将新值传递给它。单击此按钮将增加计数器:

¥The first time the button is displayed, count will be 0 because you passed 0 to useState(). When you want to change state, call setCount() and pass the new value to it. Clicking this button will increment the counter:

function MyButton() {
const [count, setCount] = useState(0);

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

return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}

React 会再次调用你的组件函数。这次,count 将是 1。然后它将是 2。以此类推。

¥React will call your component function again. This time, count will be 1. Then it will be 2. And so on.

如果多次渲染同一个组件,每个组件都会获得自己的状态。分别点击每个按钮:

¥If you render the same component multiple times, each will get its own state. Click each button separately:

import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>Counters that update separately</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

function MyButton() {
  const [count, setCount] = useState(0);

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

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

请注意每个按钮 “记住” 如何拥有自己的 count 状态并且不影响其他按钮。

¥Notice how each button “remembers” its own count state and doesn’t affect other buttons.

使用钩子

¥Using Hooks

use 开头的函数称为钩子。useState 是 React 提供的内置钩子。你可以在 API 手册 中找到其他内置的钩子。你也可以结合现有的钩子编写自己的钩子。

¥Functions starting with use are called Hooks. useState is a built-in Hook provided by React. You can find other built-in Hooks in the API reference. You can also write your own Hooks by combining the existing ones.

钩子比其他函数更具限制性。你只能在组件(或其他钩子)的顶部调用钩子。如果你想在条件或循环中使用 useState,请提取一个新组件并将其放在那里。

¥Hooks are more restrictive than other functions. You can only call Hooks at the top of your components (or other Hooks). If you want to use useState in a condition or a loop, extract a new component and put it there.

在组件之间共享数据

¥Sharing data between components

在前面的例子中,每个 MyButton 都有自己独立的 count,当每个按钮被点击时,只有被点击的按钮的 count 发生了变化:

¥In the previous example, each MyButton had its own independent count, and when each button was clicked, only the count for the button clicked changed:

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. Both MyButton components contain a count with value zero.
Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. Both MyButton components contain a count with value zero.
最初,每个 MyButtoncount 状态是 0
The same diagram as the previous, with the count of the first child MyButton component highlighted indicating a click with the count value incremented to one. The second MyButton component still contains value zero.
The same diagram as the previous, with the count of the first child MyButton component highlighted indicating a click with the count value incremented to one. The second MyButton component still contains value zero.
第一个 MyButton 将其 count 更新为 1

但是,你通常需要组件来共享数据并始终一起更新。

¥However, often you’ll need components to share data and always update together.

要使两个 MyButton 组件显示相同的 count 并一起更新,你需要将状态从单个按钮 “向上” 移动到包含所有按钮的最近组件。

¥To make both MyButton components display the same count and update together, you need to move the state from the individual buttons “upwards” to the closest component containing all of them.

在这个例子中,它是 MyApp

¥In this example, it is MyApp:

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. MyApp contains a count value of zero which is passed down to both of the MyButton components, which also show value zero.
Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. MyApp contains a count value of zero which is passed down to both of the MyButton components, which also show value zero.
最初,MyAppcount 状态是 0,并传递给两个子级
The same diagram as the previous, with the count of the parent MyApp component highlighted indicating a click with the value incremented to one. The flow to both of the children MyButton components is also highlighted, and the count value in each child is set to one indicating the value was passed down.
The same diagram as the previous, with the count of the parent MyApp component highlighted indicating a click with the value incremented to one. The flow to both of the children MyButton components is also highlighted, and the count value in each child is set to one indicating the value was passed down.
单击时,MyApp 将其 count 状态更新为 1 并将其传递给两个子级

现在,当你单击任一按钮时,MyApp 中的 count 将更改,这将更改 MyButton 中的两个计数。以下是你如何在代码中表达这一点。

¥Now when you click either button, the count in MyApp will change, which will change both of the counts in MyButton. Here’s how you can express this in code.

首先,将状态从 MyButton 上移到 MyApp

¥First, move the state up from MyButton into MyApp:

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

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

return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}

function MyButton() {
// ... we're moving code from here ...
}

然后,将状态从 MyApp 向下传递到每个 MyButton,连同共享的点击处理程序。你可以使用 JSX 大括号将信息传递给 MyButton,就像你之前使用 <img> 等内置标签所做的那样:

¥Then, pass the state down from MyApp to each MyButton, together with the shared click handler. You can pass information to MyButton using the JSX curly braces, just like you previously did with built-in tags like <img>:

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

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

return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}

像这样传递下来的信息叫做属性。现在 MyApp 组件包含 count 状态和 handleClick 事件处理程序,并将它们作为属性传递给每个按钮。

¥The information you pass down like this is called props. Now the MyApp component contains the count state and the handleClick event handler, and passes both of them down as props to each of the buttons.

最后,更改 MyButton 以读取你从其父组件传递的属性:

¥Finally, change MyButton to read the props you have passed from its parent component:

function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}

单击该按钮时,onClick 处理程序将触发。每个按钮的 onClick 属性都设置为 MyApp 中的 handleClick 函数,所以它里面的代码运行。该代码调用 setCount(count + 1),递增 count 状态变量。新的 count 值作为属性传递给每个按钮,因此它们都显示新值。这称为 “提升状态”。通过向上移动状态,你已经在组件之间共享它。

¥When you click the button, the onClick handler fires. Each button’s onClick prop was set to the handleClick function inside MyApp, so the code inside of it runs. That code calls setCount(count + 1), incrementing the count state variable. The new count value is passed as a prop to each button, so they all show the new value. This is called “lifting state up”. By moving state up, you’ve shared it between components.

import { useState } from 'react';

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

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

  return (
    <div>
      <h1>Counters that update together</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      Clicked {count} times
    </button>
  );
}

下一步

¥Next Steps

到目前为止,你已经了解了如何编写 React 代码的基础知识!

¥By now, you know the basics of how to write React code!

查看 教程 将它们付诸实践,并使用 React 构建你的第一个迷你应用。

¥Check out the Tutorial to put them into practice and build your first mini-app with React.


React 中文网 - 粤ICP备13048890号