Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(cn): translate content/docs/hooks-custom.md to Chinese #99

Merged
merged 48 commits into from
Mar 12, 2019
Merged
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
a51f03b
docs(cn): translate content/docs/hooks-custom.md to Chinese
bailnl Feb 15, 2019
9c89386
Update content/docs/hooks-custom.md
bailnl Feb 18, 2019
2d5c269
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
5caaaee
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
afd60a3
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
9ee8613
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
0333619
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
01bf897
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
257bfb9
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
8d3a268
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
ca3ebe1
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
7691deb
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
d459aa8
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
165e813
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
b4a0dfd
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
2664387
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
655c47b
Update content/docs/hooks-custom.md
yesmeck Feb 18, 2019
20e8f07
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
05282b7
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
38d7bef
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
8932442
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
c4d7d5e
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
8627551
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
dddb8d7
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
7a1cdde
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
c44ad07
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
7469707
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
a40b02a
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
bf8b3bf
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
8a7e077
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
8041ed9
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
60c3536
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
a1c4a8d
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
c47afd2
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
01e3dda
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
4a30125
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
5a33e08
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
7300dd6
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
e7fc6a0
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
8435218
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
25f2f98
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
88db86d
Update content/docs/hooks-custom.md
QC-L Mar 7, 2019
9b213ba
docs(cn): use 好友 replace 朋友, and remove original text
bailnl Mar 7, 2019
61743de
docs(cn): Make sentences more fluent
bailnl Mar 9, 2019
3e4aa24
Update content/docs/hooks-custom.md
hijiangtao Mar 11, 2019
5bb5d32
Update content/docs/hooks-custom.md
hijiangtao Mar 11, 2019
9adbae7
Update content/docs/hooks-custom.md
hijiangtao Mar 11, 2019
7a265ad
Update content/docs/hooks-custom.md
hijiangtao Mar 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions content/docs/hooks-custom.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
---
id: hooks-custom
title: Building Your Own Hooks
title: 自定义 Hooks
permalink: docs/hooks-custom.html
next: hooks-reference.html
prev: hooks-rules.html
---

*Hooks* are a new addition in React 16.8. They let you use state and other React features without writing a class.
*Hooks* React 16.8 的新增特性,允许你在不编写 class 组件的情况下使用 state React 其他特性。

Building your own Hooks lets you extract component logic into reusable functions.
通过自定义 Hooks,可以将组件逻辑提取到可重用的函数中。

When we were learning about [using the Effect Hook](/docs/hooks-effect.html#example-using-hooks-1), we saw this component from a chat application that displays a message indicating whether a friend is online or offline:
在我们学习[使用 Effect Hook](/docs/hooks-effect.html#example-using-hooks-1) 时,我们已经见过这个聊天程序中的组件,该组件用于显示好友的在线状态:

```js{4-15}
import React, { useState, useEffect } from 'react';
Expand All @@ -36,7 +36,7 @@ function FriendStatus(props) {
}
```

Now let's say that our chat application also has a contact list, and we want to render names of online users with a green color. We could copy and paste similar logic above into our `FriendListItem` component but it wouldn't be ideal:
现在我们假设聊天应用中有一个联系人列表,当用户在线时需要把名字设置为绿色。我们可以把上面类似的逻辑复制并粘贴到 `FriendListItem` 组件中来,但这并不是理想的解决方案:

```js{4-15}
import React, { useState, useEffect } from 'react';
Expand All @@ -63,15 +63,15 @@ function FriendListItem(props) {
}
```

Instead, we'd like to share this logic between `FriendStatus` and `FriendListItem`.
相反,我们希望在 `FriendStatus` `FriendListItem` 之间共享逻辑。

Traditionally in React, we've had two popular ways to share stateful logic between components: [render props](/docs/render-props.html) and [higher-order components](/docs/higher-order-components.html). We will now look at how Hooks solve many of the same problems without forcing you to add more components to the tree.
目前为止,在 React 中有两种流行的方式来共享组件之间的状态逻辑: [render props](/docs/render-props.html) 和[高阶组件](/docs/higher-order-components.html),现在让我们来看看 Hooks 是如何在让你不增加组件的情况下解决相同问题的。

## Extracting a Custom Hook {#extracting-a-custom-hook}
## 提取自定义 Hook {#extracting-a-custom-hook}

When we want to share logic between two JavaScript functions, we extract it to a third function. Both components and Hooks are functions, so this works for them too!
当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。而组件和 Hooks 都是函数,所以也同样适用这种方式。

**A custom Hook is a JavaScript function whose name starts with "`use`" and that may call other Hooks.** For example, `useFriendStatus` below is our first custom Hook:
**自定义 Hook 是一个函数,其名称以 “`use`” 开头,函数内部可以调用其他的 Hooks** 例如,下面的 `useFriendStatus` 是我们第一个自定义的 Hook:

```js{3}
import React, { useState, useEffect } from 'react';
Expand All @@ -94,11 +94,11 @@ function useFriendStatus(friendID) {
}
```

There's nothing new inside of it -- the logic is copied from the components above. Just like in a component, make sure to only call other Hooks unconditionally at the top level of your custom Hook.
此处并未包含任何新的内容——逻辑是从上述组件拷贝来的。与组件中一致,请确保只在自定义 Hook 的顶层无条件地调用其他 Hooks

Unlike a React component, a custom Hook doesn't need to have a specific signature. We can decide what it takes as arguments, and what, if anything, it should return. In other words, it's just like a normal function. Its name should always start with `use` so that you can tell at a glance that the [rules of Hooks](/docs/hooks-rules.html) apply to it.
React 组件不同的是,自定义 Hook 不需要具有特殊的标识。我们可以自由的决定它的参数是什么,以及它应该返回什么(如果需要的话)。换句话说,它就像一个正常的函数。但是它的名字应该始终以 `use` 开头,这样可以一眼看出其符合 [Hook 的规则](/docs/hooks-rules.html)

The purpose of our `useFriendStatus` Hook is to subscribe us to a friend's status. This is why it takes `friendID` as an argument, and returns whether this friend is online:
此处 `useFriendStatus` Hook 目的是订阅某个好友的在线状态。这就是我们需要将 `friendID` 作为参数,并返回这位好友的在线状态的原因。

```js
function useFriendStatus(friendID) {
Expand All @@ -110,13 +110,13 @@ function useFriendStatus(friendID) {
}
```

Now let's see how we can use our custom Hook.
现在让我们看看应该如何使用自定义 Hook

## Using a Custom Hook {#using-a-custom-hook}
## 使用自定义 Hook {#using-a-custom-hook}

In the beginning, our stated goal was to remove the duplicated logic from the `FriendStatus` and `FriendListItem` components. Both of them want to know whether a friend is online.
我们一开始的目标是在 `FriendStatus` `FriendListItem` 组件中去除重复的逻辑,即:这两个组件都想知道好友是否在线。

Now that we've extracted this logic to a `useFriendStatus` hook, we can *just use it:*
现在我们已经把这个逻辑提取到 `useFriendStatus` 的自定义 Hook 中,然后就可以*使用它了:*

```js{2}
function FriendStatus(props) {
Expand All @@ -141,19 +141,19 @@ function FriendListItem(props) {
}
```

**Is this code equivalent to the original examples?** Yes, it works in exactly the same way. If you look closely, you'll notice we didn't make any changes to the behavior. All we did was to extract some common code between two functions into a separate function. **Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.**
**这段代码等价于原来的示例代码吗?**等价,它的工作方式完全一样。如果你仔细观察,你会发现我们没有对其行为做任何的改变,我们只是将两个函数之间一些共同的代码提取到单独的函数中。**自定义 Hook 是一种自然遵循 Hooks 设计的约定,而并不是 React 的特性。**

**Do I have to name my custom Hooks starting with “`use`”?** Please do. This convention is very important. Without it, we wouldn't be able to automatically check for violations of [rules of Hooks](/docs/hooks-rules.html) because we couldn't tell if a certain function contains calls to Hooks inside of it.
**自定义 Hooks 必须以 “`use`” 开头吗?**必须如此。这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含对其内部 Hooks 的调用,React 将无法自动检查你的 Hook 是否违反了 [Hook 的规则](/docs/hooks-rules.html)

**Do two components using the same Hook share state?** No. Custom Hooks are a mechanism to reuse *stateful logic* (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.
**在两个组件中使用相同的 Hook 会共享 state?**不会。自定义 Hooks 是一种重用*状态逻辑*的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是完全隔离的。

**How does a custom Hook get isolated state?** Each *call* to a Hook gets isolated state. Because we call `useFriendStatus` directly, from React's point of view our component just calls `useState` and `useEffect`. And as we [learned](/docs/hooks-state.html#tip-using-multiple-state-variables) [earlier](/docs/hooks-effect.html#tip-use-multiple-effects-to-separate-concerns), we can call `useState` and `useEffect` many times in one component, and they will be completely independent.
**自定义 Hook 如何获取独立的 state?**每次*调用* Hook,它都会获取独立的 state。由于我们直接调用了 `useFriendStatus`,从 React 的角度来看,我们的组件只是调用了 `useState` `useEffect`。 正如我们在[之前章节](/docs/hooks-effect.html#tip-use-multiple-effects-to-separate-concerns)中[了解到的](/docs/hooks-state.html#tip-using-multiple-state-variables)一样,我们可以在一个组件中多次调用 `useState` `useEffect`,它们是完全独立的。

### Tip: Pass Information Between Hooks {#tip-pass-information-between-hooks}
### 提示:在多个 Hook 之间传递信息 {#tip-pass-information-between-hooks}

Since Hooks are functions, we can pass information between them.
由于 Hooks 本身就是函数,因此我们可以在它们之间传递信息。

To illustrate this, we'll use another component from our hypothetical chat example. This is a chat message recipient picker that displays whether the currently selected friend is online:
我们将使用聊天程序中的另一个组件来说明这一点。这是一个聊天消息接收者的选择器,它会显示当前选定的好友是否在线:

```js{8-9,13}
const friendList = [
Expand Down Expand Up @@ -184,24 +184,24 @@ function ChatRecipientPicker() {
}
```

We keep the currently chosen friend ID in the `recipientID` state variable, and update it if the user chooses a different friend in the `<select>` picker.
我们将当前选择的好友 ID 保存在 `recipientID` 状态变量中,并在用户从 `<select>` 中选择其他好友时更新这个 state。

Because the `useState` Hook call gives us the latest value of the `recipientID` state variable, we can pass it to our custom `useFriendStatus` Hook as an argument:
由于 `useState` 为我们提供了 `recipientID` 状态变量的最新值,因此我们可以将它作为参数传递给自定义的 `useFriendStatus` Hook

```js
const [recipientID, setRecipientID] = useState(1);
const isRecipientOnline = useFriendStatus(recipientID);
```

This lets us know whether the *currently selected* friend is online. If we pick a different friend and update the `recipientID` state variable, our `useFriendStatus` Hook will unsubscribe from the previously selected friend, and subscribe to the status of the newly selected one.
如此可以让我们知道*当前选中*的好友是否在线。当我们选择不同的好友并更新 `recipientID` 状态变量时,`useFriendStatusHook` 将会取消订阅之前选中的好友,并订阅新选中的好友状态。

## `useYourImagination()` {#useyourimagination}

Custom Hooks offer the flexibility of sharing logic that wasn't possible in React components before. You can write custom Hooks that cover a wide range of use cases like form handling, animation, declarative subscriptions, timers, and probably many more we haven't considered. What's more, you can build Hooks that are just as easy to use as React's built-in features.
自定义 Hooks 解决了以前在 React 组件中无法灵活共享逻辑的问题。你可以创建涵盖各种场景的自定义 Hooks,如表单处理、动画、订阅声明、计时器,甚至可能还有其他我们没想到的场景。更重要的是,创建自定义 Hooks 就像使用 React 内置的功能一样简单。

Try to resist adding abstraction too early. Now that function components can do more, it's likely that the average function component in your codebase will become longer. This is normal -- don't feel like you *have to* immediately split it into Hooks. But we also encourage you to start spotting cases where a custom Hook could hide complex logic behind a simple interface, or help untangle a messy component.
尽量避免过早地增加抽象逻辑。既然函数组件能够做的更多,那么代码库中函数组件的代码行数可能会剧增。这属于正常现象 —— 不必立即将它们拆分为 Hooks。但我们仍鼓励你能通过自定义 Hooks 寻找可能,以达到简化代码逻辑,解决组件杂乱无章的目的。

For example, maybe you have a complex component that contains a lot of local state that is managed in an ad-hoc way. `useState` doesn't make centralizing the update logic any easier so might you prefer to write it as a [Redux](https://redux.js.org/) reducer:
例如,有个复杂的组件,其中包含了大量以特殊的方式来管理的内部状态。`useState` 并不会使得集中更新逻辑变得容易,因此你可能更愿意使用 [redux](http://redux.js.org/) 中的 reducer 来编写。

```js
function todosReducer(state, action) {
Expand All @@ -218,9 +218,9 @@ function todosReducer(state, action) {
}
```

Reducers are very convenient to test in isolation, and scale to express complex update logic. You can further break them apart into smaller reducers if necessary. However, you might also enjoy the benefits of using React local state, or might not want to install another library.
Reducers 非常便于单独测试,且易于扩展,以表达复杂的更新逻辑。如有必要,您可以将它们分成更小的 reducer。但是,你可能还享受着 React 内部 state 带来的好处,或者可能根本不想安装其他库。

So what if we could write a `useReducer` Hook that lets us manage the *local* state of our component with a reducer? A simplified version of it might look like this:
那么,为什么我们不编写一个 `useReducer` Hook,使用 reducer 的方式来管理组件的内部 state 呢?其简化版本可能如下所示:

```js
function useReducer(reducer, initialState) {
Expand All @@ -235,7 +235,7 @@ function useReducer(reducer, initialState) {
}
```

Now we could use it in our component, and let the reducer drive its state management:
在组件中使用它,让 reducer 驱动它管理 state

```js{2}
function Todos() {
Expand All @@ -249,4 +249,4 @@ function Todos() {
}
```

The need to manage local state with a reducer in a complex component is common enough that we've built the `useReducer` Hook right into React. You'll find it together with other built-in Hooks in the [Hooks API reference](/docs/hooks-reference.html).
在复杂组件中使用 reducer 管理内部 state 的需求很常见,我们已经将 `useReducer` Hook 内置到 React 中。你可以在 [Hooks API 参考](/docs/hooks-reference.html)中找到它使用,搭配其他内置的 Hook 一起使用。