Skip to content

Commit

Permalink
docs(cn): translate warnings/invalid-hook-call-warning to Chinese (#1153
Browse files Browse the repository at this point in the history
)

Co-authored-by: Yucohny <yucohny@163.com>
  • Loading branch information
JohnhanLiu and Yucohny authored Jun 29, 2023
1 parent 4ec3d78 commit 60b5ed9
Showing 1 changed file with 44 additions and 44 deletions.
88 changes: 44 additions & 44 deletions src/content/warnings/invalid-hook-call-warning.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,68 @@
---
title: Rules of Hooks
title: Hook 规则
---

You are probably here because you got the following error message:
你进入到这个页面,大概是因为遇到了下面这个错误提示:

<ConsoleBlock level="error">

Hooks can only be called inside the body of a function component.

</ConsoleBlock>

There are three common reasons you might be seeing it:
通常有以下 3 个错误原因:

1. You might be **breaking the Rules of Hooks**.
2. You might have **mismatching versions** of React and React DOM.
3. You might have **more than one copy of React** in the same app.
1. 你可能 **打破了 Hook 的使用规则**
2. 你可能使用了 **版本不一致** React React DOM
3. 你可能在同一个应用当中使用了 **重复的 React 引用**

Let's look at each of these cases.
让我们来逐个看看这些问题。

## Breaking Rules of Hooks {/*breaking-rules-of-hooks*/}
## 打破了 Hook 的使用规则 {/*breaking-rules-of-hooks*/}

Functions whose names start with `use` are called [*Hooks*](/reference/react) in React.
在 React 中被调用的且以 `use` 开头命名的函数叫 [**Hook**](/reference/react)

**Don’t call Hooks inside loops, conditions, or nested functions.** Instead, always use Hooks at the top level of your React function, before any early returns. You can only call Hooks while React is rendering a function component:
**不要在循环语句内、条件语句后或嵌套的函数内调用 Hook**。反之,应该始终保证 Hook 在函数式组件的顶层,并避免在 Hook 调用前过早终止函数。你只能在 React 渲染函数式组件的过程当中调用 Hook:

*Call them at the top level in the body of a [function component](/learn/your-first-component).
*Call them at the top level in the body of a [custom Hook](/learn/reusing-logic-with-custom-hooks).
*[函数式组件](/learn/your-first-component) 内部的顶级作用域调用他们。
*[自定义 Hook](/learn/reusing-logic-with-custom-hooks) 内部的顶级作用域调用他们。

```js{2-3,8-9}
function Counter() {
// ✅ Good: top-level in a function component
// ✅ 正确:函数式组件的顶级作用域
const [count, setCount] = useState(0);
// ...
}
function useWindowWidth() {
// ✅ Good: top-level in a custom Hook
// ✅ 正确:自定义 Hook 的顶级作用域
const [width, setWidth] = useState(window.innerWidth);
// ...
}
```

It’s **not** supported to call Hooks (functions starting with `use`) in any other cases, for example:
以下有几个要点,这些情况下 **** 支持调用 Hook(以 `use` 开头的函数),例如:

* 🔴 Do not call Hooks inside conditions or loops.
* 🔴 Do not call Hooks after a conditional `return` statement.
* 🔴 Do not call Hooks in event handlers.
* 🔴 Do not call Hooks in class components.
* 🔴 Do not call Hooks inside functions passed to `useMemo`, `useReducer`, or `useEffect`.
* 🔴 不要在条件语句内或循环语句内调用 Hook。
* 🔴 不要在包含 `return` 的条件语句之后调用 Hook。
* 🔴 不要在事件监听中调用 Hook。
* 🔴 不要在类式组件内调用 Hook。
* 🔴 不要在那些传给 `useMemo``useReducer` `useEffect` 的函数内调用 Hook。

If you break these rules, you might see this error.
如果你打破了这些规则,你可能就会看到这个错误提示。

```js{3-4,11-12,20-21}
function Bad({ cond }) {
if (cond) {
// 🔴 Bad: inside a condition (to fix, move it outside!)
// 🔴 错误:在条件语句内调用(修复办法:把它挪到外层!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad() {
for (let i = 0; i < 10; i++) {
// 🔴 Bad: inside a loop (to fix, move it outside!)
// 🔴 错误:在循环内调用(修复办法:把它挪到外层!)
const theme = useContext(ThemeContext);
}
// ...
Expand All @@ -72,22 +72,22 @@ function Bad({ cond }) {
if (cond) {
return;
}
// 🔴 Bad: after a conditional return (to fix, move it before the return!)
// 🔴 错误:在包含 return 的条件语句后调用(修复办法:挪到 return 之前!)
const theme = useContext(ThemeContext);
// ...
}
function Bad() {
function handleClick() {
// 🔴 Bad: inside an event handler (to fix, move it outside!)
// 🔴 错误:在事件监听器或回调中调用(修复办法:把它挪到外层!)
const theme = useContext(ThemeContext);
}
// ...
}
function Bad() {
const style = useMemo(() => {
// 🔴 Bad: inside useMemo (to fix, move it outside!)
// 🔴 错误:在 useMemo 内调用(修复办法:把它挪到外层!)
const theme = useContext(ThemeContext);
return createStyle(theme);
});
Expand All @@ -96,63 +96,63 @@ function Bad() {
class Bad extends React.Component {
render() {
// 🔴 Bad: inside a class component (to fix, write a function component instead of a class!)
// 🔴 错误:在类式组件内调用(修复办法:写一个函数式组件而不是类式组件!)
useEffect(() => {})
// ...
}
}
```

You can use the [`eslint-plugin-react-hooks` plugin](https://www.npmjs.com/package/eslint-plugin-react-hooks) to catch these mistakes.
你可以借助 [`eslint-plugin-react-hooks` 插件](https://www.npmjs.com/package/eslint-plugin-react-hooks) 来帮你提前暴露这些错误。

<Note>

[Custom Hooks](/learn/reusing-logic-with-custom-hooks) *may* call other Hooks (that's their whole purpose). This works because custom Hooks are also supposed to only be called while a function component is rendering.
[自定义 Hook](/learn/reusing-logic-with-custom-hooks) **可能** 被其他的 Hook 调用 (这仍然符合设计初衷)。为什么呢?因为自定义 Hook 也是被设定为只能在函数式组件渲染过程中被调用。

</Note>

## Mismatching Versions of React and React DOM {/*mismatching-versions-of-react-and-react-dom*/}
## 版本不一致的 React React DOM {/*mismatching-versions-of-react-and-react-dom*/}

You might be using a version of `react-dom` (< 16.8.0) or `react-native` (< 0.59) that doesn't yet support Hooks. You can run `npm ls react-dom` or `npm ls react-native` in your application folder to check which version you're using. If you find more than one of them, this might also create problems (more on that below).
你可能正在使用一个还不支持 Hook 的版本,例如 `react-dom`< 16.8.0)或 `react-native`< 0.59)。你可以在你的应用目录下执行 `npm ls react-dom` `npm ls react-native` 来检查下你正在使用的版本。如果你发现了同一个包有多个版本,那也可能带来其他的问题(下文会详细展开)。

## Duplicate React {/*duplicate-react*/}
## 重复的 React {/*duplicate-react*/}

In order for Hooks to work, the `react` import from your application code needs to resolve to the same module as the `react` import from inside the `react-dom` package.
为了使 Hook 正常工作,你需要确保你应用代码中所引用的 `react` `react-dom` 内部使用的 `react` 是同一个来源。

If these `react` imports resolve to two different exports objects, you will see this warning. This may happen if you **accidentally end up with two copies** of the `react` package.
如果上述的两个 `react` 是使用不同模块导出的值,你可能会看到这个警告信息。一般来说,原因都会是你 **意外地使用了重复的** `react` 包。

If you use Node for package management, you can run this check in your project folder:
如果你用的是 Node 进行包管理,你可以在你的应用目录下执行这个命令做个检查:

<TerminalBlock>

npm ls react

</TerminalBlock>

If you see more than one React, you'll need to figure out why this happens and fix your dependency tree. For example, maybe a library you're using incorrectly specifies `react` as a dependency (rather than a peer dependency). Until that library is fixed, [Yarn resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) is one possible workaround.
如果你看到了超过 1 个 `React`,你可能需要去搞明白为什么会这样,并且修复一下你的包依赖关系。举个例子:你可能用了一个包,其内部错误地声明了 `react` 作为它的依赖(推荐做法应该是在 peerDependency 中)。在这个包被修复之前,[yarn resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) 可以作为一个临时解决办法。

You can also try to debug this problem by adding some logs and restarting your development server:
你也可以通过增加一些日志,然后重启你的开发服务器,这样你就可以自己来调试这个问题了:

```js
// Add this in node_modules/react-dom/index.js
// 把下面这行加在 node_modules/react-dom/index.js
window.React1 = require('react');

// Add this in your component file
// 把下面这几行加入到你的组件逻辑中
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);
```

If it prints `false` then you might have two Reacts and need to figure out why that happened. [This issue](https://github.com/facebook/react/issues/13991) includes some common reasons encountered by the community.
如果你在控制台看到打印了 `false`,那代表你的项目中存在两个 React,你需要搞明白这是为什么。[ issue](https://github.com/facebook/react/issues/13991) 列举了一些常见的可能的原因。

This problem can also come up when you use `npm link` or an equivalent. In that case, your bundler might "see" two Reacts — one in application folder and one in your library folder. Assuming `myapp` and `mylib` are sibling folders, one possible fix is to run `npm link ../myapp/node_modules/react` from `mylib`. This should make the library use the application's React copy.
如果你使用了 `npm link` 或者同类操作,也有可能导致这个问题出现。在这种情况下,你的构建工具可能会“看到”两个不同的 React——一个在应用目录,另一个则在工具库的目录。假设 `myapp` `mylib` 是两个相邻的目录,一个可能有效的解决办法是在 `mylib` 目录下执行 `npm link ../myapp/node_modules/react`,这样就能让工具库里面使用的 React 和你应用里面使用的是同一个了。

<Note>

In general, React supports using multiple independent copies on one page (for example, if an app and a third-party widget both use it). It only breaks if `require('react')` resolves differently between the component and the `react-dom` copy it was rendered with.
通常来讲,在一个页面上使用多个相互独立的 React 是完全没问题的(举个例子,应用和第三方库同时使用各自的 React)。只有当你组件里引用的 `react``react-dom` 里引用的 `react` 不一致时,才会导致这个报错。

</Note>

## Other Causes {/*other-causes*/}
## 其他原因 {/*other-causes*/}

If none of this worked, please comment in [this issue](https://github.com/facebook/react/issues/13991) and we'll try to help. Try to create a small reproducing example — you might discover the problem as you're doing it.
如果上文没有解决你的问题,你可以在 [ issue](https://github.com/facebook/react/issues/13991) 中提交评论,我们会积极地提供帮助。评论的时候,如果能提供一个小的、能复现的示例那最好不过了。

0 comments on commit 60b5ed9

Please sign in to comment.