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 1 commit
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
67 changes: 34 additions & 33 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,16 @@ 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),我们现在将看看 Hook 是如何在不强制添加更多组件的情况下解决相同的问题。

## 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 +95,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 的顶层无条件(译者注:如if,三元等)地调用其他 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:
我们这个 Hook `useFriendStatus` 的目的是订阅某个朋友的在线状态。这也就是为什么我们需要 `friendID` 作为参数,并返回这位朋友的是否在线状态。

```js
function useFriendStatus(friendID) {
Expand All @@ -110,13 +111,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 +142,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.
**我必须以 “`use`” 开头来自定义 Hooks 吗?** 请这么做。这个约定非常重要。没有它,React 无法自动检查是否违反了[Hook 的规则](/docs/hooks-rules.html),因为我们无法判断某个函数是否包含了 Hooks 的调用。

**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 会共享状态吗?** 不会。自定义 Hooks 是一种重用*有状态逻辑*的机制(例如设置订阅并记住当前值),所以每次使用自定义 Hook 时,其中的所有 `state` 和 `effect` 都是完全隔离的。

**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如何获得隔离状态?** 每次对Hook的*调用*都会被隔离状态. 因为我们直接调用 `useFriendStatus`,从 React 的角度来看,我们的组件只是调用了`useState` `useEffect`. 正如我们前面的章节了解到的([tip:使用多个state](/docs/hooks-state.html#tip-using-multiple-state-variables) 和 [tip: 使用多个effect分离问题](/docs/hooks-effect.html#tip-use-multiple-effects-to-separate-concerns)),我们可以在一个组件中调用 `useState` `useEffect` 很多次,它们将是完全独立的。

### Tip: Pass Information Between Hooks {#tip-pass-information-between-hooks}
### Tip: 在多个 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 +185,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>` 中选择了其他的朋友,我们就更新这个变量。

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` 状态变量的最新值,所以我们可以将它作为参数传递给我们的自定义 Hook `useFriendStatus`

```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,去涵盖各种用例,如表单处理,动画,声明订阅,计时器,以及可能还有更多我们未考虑过的用例。更重要的是,你可以编写与 React 的内置特性一样易于使用的 Hooks。

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.
尽量不要过早地添加抽象。既然函数组件可以做得更多,那么代码库中平均函数组件很可能会变得更长。这是正常的——不要觉得你必须立即将其拆分为 Hook。但我们鼓励你去发现可以通过自定义 Hook 将复杂的逻辑隐藏在简单的界面背后或者能解放组件混乱的情况。

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 +219,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 本地状态的好处,或者可能不想安装其他库。

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 管理组件的本地状态呢?它的简化版本可能如下所示:

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

Now we could use it in our component, and let the reducer drive its state management:
现在我们可以在我们的组件中使用它,让 reducer 驱动它的状态管理:

```js{2}
function Todos() {
Expand All @@ -249,4 +250,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 管理本地状态的需求很常见,我们已经将 `useReducer` Hook 内置到 React 中。你可以在[Hooks API 参考](/docs/hooks-reference.html)中找到它与其他内置的 Hook 一起使用。