From 9f6037e3f30877d7dc38a595087c9097ed1a6af4 Mon Sep 17 00:00:00 2001 From: zhaozhiwei Date: Thu, 4 Nov 2021 14:10:04 +0800 Subject: [PATCH 01/32] docs(cn): keeping-components-pure --- .../pages/learn/keeping-components-pure.md | 164 +++++++++--------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 0f65247504..09a4321786 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -1,41 +1,43 @@ --- -title: Keeping Components Pure +title: 保持组件的纯净 +translators: + - 7ooz --- -Some JavaScript functions are "pure." Pure functions only perform a calculation and nothing more. By strictly only writing your components as pure functions, you can avoid an entire class of baffling bugs and unpredictable behavior as your codebase grows. To get these benefits, though, there are a few rules you must follow. +一些 JavaScript 函数是“纯”的。纯函数仅仅执行计算,不做其他事情。将组件严格编写为纯函数,你可以避免随着代码库的增长而出现一整类令人困扰的 bugs 和不可预测的行为。但为了获得这些好处,你需要遵循一些规则。 -* What purity is and how it helps you avoid bugs -* How to keep components pure by keeping changes out of the render phase -* How to use Strict Mode to find mistakes in your components +* 纯函数是什么,以及它如何帮助你避免 bugs +* 如何将更改置于渲染阶段外,以保持组件的纯净 +* 如何使用严格模式找到组件中的错误 -## Purity: Components as formulas +## 纯函数:组件作为公式 {#purity-components-as-formulas} -In computer science (and especially the world of functional programming), [a pure function](https://wikipedia.org/wiki/Pure_function) is a function with the following characteristics: +在计算机科学中(尤其是函数式编程的世界中),一个[纯函数](https://wikipedia.org/wiki/Pure_function)具有如下特征: -* **Minds its own business.** It does not change any objects or variables that existed before it was called. -* **Same inputs, same output.** Given the same inputs, a pure function should always return the same result. +* **只负责自己的任务**。它不会更改在该函数调用前便存在的对象或变量。 +* **输入相同,则输出相同**。给定相同的输入,纯函数应总是返回相同的结果。 -You might already be familiar with one example of pure functions: formulas in math. +你也许已经熟悉了纯函数的一个例子:数学中的公式。 -Consider this math formula: y = 2x. +考虑如下数学公式:y = 2x。 -If x = 2 then y = 4. Always. +若 x = 2y = 4。 永远如此。 -If x = 3 then y = 6. Always. +若 x = 3y = 6。 永远如此。 -If x = 3, y won't sometimes be 9 or –1 or 2.5 depending on the time of day or the state of the stock market. +若 x = 3,那么 y 不会受当前时段或股市状况影响,而等于 9–12.5。 -If y = 2x and x = 3, y will _always_ be 6. +若 y = 2xx = 3, 那么 y _永远_ 等于 6. -If we made this into a JavaScript function, it would look like this: +我们使用 JavaScript 的函数实现,看起来将会是这样: ```js function double(number) { @@ -43,9 +45,9 @@ function double(number) { } ``` -In the above example, `double()` is a **pure function.** If you pass it `3`, it will return `6`. Always. +上述例子中,`double()` 就是一个**纯函数**。如果你传入 `3` ,它将总是返回 `6` 。 -React is designed around this concept. **React assumes that every component you write is a pure function.** This means that React components you write must always return the same JSX given the same inputs: +React 便围绕着这个概念进行设计。它假设你编写的所有组件都是纯函数,对于相同的输入,必须总是返回相同的 JSX。 @@ -75,21 +77,21 @@ export default function App() { -When you pass `drinkers={1}` to `Recipe`, it will return JSX containing `1 cups of milk`. Always. +当你传入参数 `drinkers={1}` 至 `Recipe` 函数,它将返回包含 `1 cups of milk` 的 JSX。 -If you pass `drinkers={4}`, it will return JSX containing `4 cups of milk`. Always. +而当你传入参数 `drinkers={4}`,它将返回包含 `4 cups of milk` 的 JSX。 -Just like a math formula. +就像数学公式一样。 -You could think of your components as recipes: if you follow them and don't introduce new ingredients during the cooking process, you will get the same dish every time. That "dish" is the JSX that the component serves to React to [render](render-and-commit). +你可以把你的组件当作食谱:如果你遵循它们,并且在烹饪过程中不引入新食材,你每次都会得到相同的菜肴。那道“菜肴”就是组件用于 React [渲染](render-and-commit)的 JSX。 -## Side Effects: (un)intended consequences +## 副作用:(无)意识后果 {#side-effects-unintended-consequences} -React's rendering process must always be pure. Components should only *return* their JSX, and not *change* any objects or variables that existed before rendering—that would make them impure! +React 的渲染过程必须始终是纯的。组件应该只*返回* 它们的 JSX,而不*改变* 在渲染前存在的任何对象或变量——这将会使它们变得不纯! -Here is a component that breaks this rule: +以下是违反这一规则的组件示例: @@ -115,11 +117,11 @@ export default function TeaSet() { -This component is reading and writing a `guest` variable declared outside of it. This means that **calling this component multiple times will produce different JSX!** And what's more, if _other_ components read `guest`, they will produce different JSX, too, depending on when they were rendered! That's not predictable. +该组件正在读写在其外部声明的 `guest` 变量。这意味着**多次调用这个组件会产生不同的 JSX!**并且,如果其他组件读取 `guest` ,它们也会产生不同的 JSX,其结果取决于它们何时被渲染!这是不可预测的。 -Going back to our formula y = 2x, now even if x = 2, we cannot trust that y = 4. Our tests could fail, our users would be baffled, planes would fall out of the sky—you can see how this would lead to confusing bugs! +回到我们的公式 y = 2x ,现在即使 x = 2 ,我们也不能相信 y = 4 。我们的测试可能会失败,我们的用户可能会感到困扰,飞机可能会从天空坠毁——你将看到这会引发多么扑朔迷离的 bugs! -You can fix this component by [passing `guest` as a prop instead](/learn/passing-props-to-a-component): +你可以[将 `guest` 作为 prop 传入](/learn/passing-props-to-a-component)来修复此组件: @@ -141,29 +143,29 @@ export default function TeaSet() { -Now your component is pure, as the JSX it returns only depends on the `guest` prop. +现在你的组件就是纯的了,因为它返回的 JSX 只依赖于 `guest` prop。 -In general, you should not expect your components to be rendered in any particular order. It doesn't matter if you call y = 2x before or after y = 5x: both formulas will resolve independently of each other. In the same way, each component should only "think for itself," and not attempt to coordinate with or depend upon others during rendering. Rendering is like a school exam: each component should calculate JSX on their own! +一般来说,你不应该期望你的组件以任何特定的顺序被渲染。调用 y = 5xy = 2x 的先后顺序并不重要:这两个公式相互独立。同样地,每个组件也应该“独立思考”,而不是在渲染过程中试图与其他组件协调,或者依赖于其他组件。渲染过程就像是一场学校考试:每个组件都应该自己计算 JSX! - + -Although you might not have used them all yet, in React there are three kinds of inputs that you can read while rendering: [props](/learn/passing-props-to-a-component), [state](/learn/state-a-components-memory), and [context](/learn/passing-data-deeply-with-context). You should always treat these inputs as read-only. +尽管你可能还没有全部使用过它们,但在 React 中,你可以在渲染时读取三种输入:[props](/learn/passing-props-to-a-component), [state](/learn/state-a-components-memory), 和 [context](/learn/passing-data-deeply-with-context)。你应该始终将这些输入视为只读。 -When you want to *change* something in response to user input, you should [set state](/learn/state-a-components-memory) instead of writing to a variable. You should never change preexisting variables or objects while your component is rendering. +当你想根据用户输入更改某些内容时,你应该[设置状态](/learn/state-a-components-memory)而不是写入变量。当你的组件正在渲染时,你永远不应该改变预先存在的变量或对象。 -React offers a "Strict Mode" in which it calls each component's function twice during development. **By calling the component functions twice, Strict Mode helps find components that break these rules.** +React 提供了“严格模式”,在严格模式下开发时,它将两次调用组件函数。**通过重复调用组件函数,严格模式有助于找到违反这些规则的组件**。 -Notice how the original example displayed "Guest #2", "Guest #4", and "Guest #6" instead of "Guest #1", "Guest #2", and "Guest #3". The original function was impure, so calling it twice broke it. But the fixed pure version works even if the function is called twice every time. **Pure functions only calculate, so calling them twice won't change anything**--just like calling `double(2)` twice doesn't change what's returned, and solving y = 2x twice doesn't change what y is. Same inputs, same outputs. Always. +我们注意到,原始示例显示的是“Guest #2”、“Guest #4”和“Guest #6”,而不是“Guest #1”、“Guest #2”和“Guest #3”。原来的函数是不纯的,调用它两次破坏了它。但对于固定的纯函数版本,即使调用该函数两次也能得到正确结果。**纯函数仅仅执行计算,因此两次调用它们不会改变任何东西**——就像两次调用 `double(2)` 不会改变返回的内容,两次求解 y = 2x 不会改变 y 的值一样。相同的输入,总是返回相同的输出。 -Strict Mode has no effect in production, so it won't slow down the app for your users. To opt into Strict Mode, you can wrap your root component into ``. Some frameworks do this by default. +严格模式在生产环境下会失效,因此它不会降低应用程序的速度。如需引入严格模式,你可以将根组件包装到 `` 中。一些框架会默认这样做。 -### Local mutation: Your component's little secret +### 局部 mutation:组件的小秘密 {#local-mutation-your-components-little-secret} -In the above example, the problem was that the component changed a *preexisting* variable while rendering. This is often called a **"mutation"** to make it sound a bit scarier. Pure functions don't mutate variables outside of the function's scope or objects that were created before the call—that makes them impure! +上述例子里,问题出在渲染过程中,组件改变了 *preexisting* 变量的值。这种行为通常被称为 **“mutation”** ,以使其听起来更可怕。纯函数不会改变函数作用域外的变量或在函数调用前创建的对象——这使它们变得不纯! -However, **it's completely fine to change variables and objects that you've *just* created while rendering.** In this example, you create an `[]` array, assign it to a `cups` variable, and then `push` a dozen cups into it: +但是,**在渲染时更改你 *刚刚* 创建的变量和对象完全没问题**。在本例中,你创建一个 `[]` 数组,将其分配给一个 `cups` 变量,然后 `push` 一打 cups 进去: @@ -183,41 +185,41 @@ export default function TeaGathering() { -If the `cups` variable or the `[]` array were created outside the `TeaGathering` function, this would be a huge problem! You would be changing a *preexisting* object by pushing items into that array. +如果 `cups` 变量或 `[]` 数组是在 `TeaGathering` 函数之外创建的,这将是一个巨大的问题!你调用的数组 push 方法将更改*预先存在的* 对象。 -However, it's fine because you've created them *during the same render*, inside `TeaGathering`. No code outside of `TeaGathering` will ever know that this happened. This is called **"local mutation"**—it's like your component's little secret. +但是,这里不会有影响,因为每次渲染时,你都是在 `TeaGathering` 函数内部创建的它们。 `TeaGathering` 之外的代码不会知道发生了什么。这就被称为 **“局部 mutation”** ——如同藏在组件里的小秘密。 -## Where you _can_ cause side effects +## 哪里可能引发副作用 {#where-you-can-cause-side-effects} -While functional programming relies heavily on purity, at some point, somewhere, _something_ has to change. That's kind of the point of programming! These changes—updating the screen, starting an animation, changing the data—are called **side effects**. They're things that happen _"on the side,"_ not during rendering. +函数式编程在很大程度上依赖于纯函数,但某些事物在特定情况下不得不发生改变。这是编程的要义!这些变动——更新屏幕、启动动画、更改数据——被称为**副作用**。它们是 _“额外”_ 发生的事情,与渲染过程无关。 -In React, **side effects usually belong inside [event handlers](/learn/responding-to-events).** Event handlers are functions that React runs when you perform some action—for example, when you click a button. Even though event handlers are defined *inside* your component, they don't run *during* rendering! **So event handlers don't need to be pure.** +在 React 中,**副作用通常属于[事件处理程序](/learn/responding-to-events)。** 事件处理程序是 React 在你执行某些操作——例如,当单击按钮时——运行的函数。即使事件处理程序是在你的组件*内部* 定义的,它们也不会在渲染期间运行! **因此事件处理程序不需要是纯函数。** -If you've exhausted all other options and can't find the right event handler for your side effect, you can still attach it to your returned JSX with a [`useEffect`](/reference/useeffect) call in your component. This tells React to execute it later, after rendering, when side effects are allowed. **However, this approach should be your last resort.** +如果你用尽一切选项,仍无法为副作用找到合适的事件处理程序的话,你还可以调用组件中的 [`useEffect`](/reference/useeffect) 方法将其附加到返回的 JSX 中。这告诉 React 在渲染结束后执行它。**然而,这种方法应该是你最后的手段。** -When possible, try to express your logic with rendering alone. You'll be surprised how far this can take you! +如果可能,请尝试仅通过渲染过程来表达你的逻辑。你会惊讶于这能带给你多少好处! - + -Writing pure functions takes some habit and discipline. But it also unlocks marvelous opportunities: +编写纯函数需要一些习惯和纪律。但它也带来了绝妙的机会: -* Your components could run in a different environment—for example, on the server! Since they return the same result for the same inputs, one component can serve many user requests. -* You can improve performance by [skipping rendering](/learn/skipping-unchanged-trees) components whose inputs have not changed. This is safe because pure functions always return the same results, so they are safe to cache. -* If some data changes in the middle of rendering a deep component tree, React can restart rendering without wasting time to finish the outdated render. Purity makes it safe to stop calculating at any time. +* 你的组件可以在不同的环境下运行——例如,在服务器上!由于它们针对相同的输入,总是返回相同的结果,因此一个组件可以满足多个用户请求。 +* 对于输入未更改的组件,你可以[跳过渲染](/learn/skiping-unchanged-trees)来提高性能。这是安全的做法,因为纯函数总是返回相同的结果,所以它们可以安全地缓存。 +* 如果在渲染深层组件树的过程中某些数据发生了变化,React 可以重新开始渲染,而不会浪费时间完成过时的渲染。纯函数使得它可以随时安全地停止计算。 -Every new React feature we're building takes advantage of purity. From data fetching to animations to performance, keeping components pure unlocks the power of the React paradigm. +我们正在构建的每个 React 新功能都利用到了纯函数。从数据获取到动画再到性能,保持组件的纯净可以充分释放 React 范式的能力。 -* A component must be pure, meaning: - * **Mind its own business.** It should not change any objects or variables that existed before rendering. - * **Same inputs, same output.** Given the same inputs, a component should always return the same JSX. -* Rendering can happen at any time, so components should not depend on each others' rendering sequence. -* You should not mutate any of the inputs that your components use for rendering. That includes props, state, and context. To update the screen, ["set" state](reacting-to-input-with-state) instead of mutating preexisting objects. -* Strive to express your component's logic in the JSX you return. When you need to "change things," you'll usually want to do it in an event handler. As a last resort, you can `useEffect`. -* Writing pure functions takes a bit of practice, but it unlocks the power of React's paradigm. +* 一个组件必须是纯的,意味着: + * **只负责自己的任务。** 不应更改渲染前存在的任何对象或变量。 + * **输入相同,则输出相同。** 给定相同的输入,组件应该总是返回相同的 JSX。 +* 渲染随时可能发生,因此组件不应依赖于彼此的渲染顺序。 +* 你不应该改变组件用于渲染的输入。这包括 props、state 和 context。如需更新界面,["设置"状态](reacting-to-input-with-state) 而不是改变预先存在的对象。 +* 努力在你返回的 JSX 中表达你的组件逻辑。当你需要“改变事物”时,你通常希望在事件处理程序中进行。作为最后的手段,你可以使用 `useEffect`。 +* 编写纯函数需要一些练习,但它充分释放了 React 范式的能力。 @@ -225,15 +227,15 @@ Every new React feature we're building takes advantage of purity. From data fetc -### Fix a broken clock +### 修复坏掉的时钟 -This component tries to set the `

`'s CSS class to `"night"` during the time from midnight to six hours in the morning, and `"day"` at all other times. However, it doesn't work. Can you fix this component? +该组件尝试将 `

` 的 CSS 类设置为从午夜到早上 6 小时的时间为 `"night"`,而在所有其他时间为 `"day"`。但它不起作用。你能修复这个组件吗? -You can verify whether your solution works by temporarily changing the computer's timezone. When the current time is between midnight and six in the morning, the clock should have inverted colors! +你可以临时更改计算机的时区来验证你的解决方案是否有效。当前时间位于午夜至早上六点之间时,时钟应该有相反的颜色! -Rendering is a *calculation*, it shouldn't try to "do" things. Can you express the same idea differently? +渲染是一种*计算过程* ,它不应该试图“做”其他事情。你能用其他方式表达和这一样的想法吗? @@ -297,7 +299,7 @@ body > * { -You can fix this component by calculating the `className` and including it in the render output: +你可以计算 className,并将其包含在渲染的输出中,以此实现对组件的修复: @@ -358,19 +360,19 @@ body > * { -In this example, the side effect (modifying the DOM) was not necessary at all. You only needed to return JSX. +在这个例子中,副作用(修改 DOM)完全没有必要。你只需要返回 JSX。 -### Fix a broken profile +### 修复损坏的名片 -Two `Profile` components are rendered side by side with different data. Press "Collapse" on the first profile, and then "Expand" it. You'll notice that both profiles now show the same person. This is a bug. +两个 `Profile` 组件使用不同的数据并排呈现。在第一张名片上点击“Collapse”折叠,然后点击“Expand”展开它。你会看到两张名片现在显示的是同一个人。这是一个 bug。 -Find the cause of the bug and fix it. +找出产生 bug 的原因,并修复它。 -The buggy code is in `Profile.js`. Make sure you read it all from top to bottom! +问题代码出现在 `Profile.js` 中。一定要从上到下读完所有内容! @@ -471,9 +473,9 @@ h1 { margin: 5px; font-size: 18px; } -The problem is that the `Profile` component writes to a preexisting variable called `currentPerson`, and the `Header` and `Avatar` components read from it. This makes *all three of them* impure and difficult to predict. +问题在于 `Profile` 组件写入了一个预先存在的 `currentPerson` 变量,而 `Header` 和 `Avatar` 组件从中读取了这个变量。这使得*所有三个* 组件都变得不纯并且难以预测。 -To fix the bug, remove the `currentPerson` variable. Instead, pass all information from `Profile` to `Header` and `Avatar` via props. You'll need to add a `person` prop to both components and pass it all the way down. +要修复这个 bug,需要删除 `currentPerson` 变量。然后以 props 作为替代,将所有信息从 `Profile` 传递到 `Header` 和 `Avatar` 中。你需要向两个组件添加一个 `person` 属性并将其一直向下传递。 @@ -567,15 +569,15 @@ h1 { margin: 5px; font-size: 18px; } -Remember that React does not guarantee that component functions will execute in any particular order, so you can't communicate between them by setting variables. All communication must happen through props. +请记住,React 无法保证组件函数以任何特定的顺序执行,因此你无法通过设置变量在它们之间进行通信。所有的交流都必须通过 props 进行。 -### Fix a broken story tray +### 修复损坏的故事托盘 -The CEO of your company is asking you to add "stories" to your online clock app, and you can't say no. You've written a `StoryTray` component that accepts a list of `stories`, followed by a "Create Story" placeholder. +你所在公司的 CEO 要求你在你的在线时钟 app 中添加“故事”,你不能拒绝。你已经编写了一个 `StoryTray` 组件,它接受一个 `stories` 列表,后跟一个 “Create Story” 占位符。 -You implemented the "Create Story" placeholder by pushing one more fake story at the end of the `stories` array that you receive as a prop. But for some reason, "Create Story" appears more than once. Fix the issue. +你在作为 props 的 `stories` 数组末尾 push 了一个假故事来实现 “Create Story” 占位符。但出于某种原因,“Create Story” 出现了不止一次。请修复这个问题。 @@ -671,11 +673,11 @@ li { -Notice how whenever the clock updates, "Create Story" is added *twice*. This serves as a hint that we have a mutation during rendering--Strict Mode calls components twice to make these issues more noticeable. +请注意,每当时钟更新时,“Create Story” 都会被添加*两次*。这暗示我们在渲染过程中发生了 mutation——严格模式调用组件两次可以使这些问题更加明显。 -`StoryTray` function is not pure. By calling `push` on the received `stories` array (a prop!), it is mutating an object that was created *before* `StoryTray` started rendering. This makes it buggy and very difficult to predict. +`StoryTray` 的功能不纯。通过在接收到的 `stories` 数组(一个 prop!)上调用 `push` 方法,它正改变着一个在 `StoryTray` 渲染*之前* 创建的对象。这使得它有问题并且难以预测。 -The simplest fix is to not touch the array at all, and render "Create Story" separately: +最简单的解决方案是完全不碰数组,单独渲染 “Create Story”: @@ -759,7 +761,7 @@ li { -Alternatively, you could create a _new_ array (by copying the existing one) before you push an item into it: +或者,你可以在将 item 项 push 进去之前创建一个 _新_ 数组(通过复制现有数组): @@ -851,9 +853,9 @@ li { -This keeps your mutation local and your rendering function pure. However, you still need to be careful: for example, if you tried to change any of the array's existing items, you'd have to clone those items too. +这使你的 mutation 保持在局部,并使你的渲染函数保持纯净。但你仍然需要小心:例如,当你想要更改数组的任意项时,必须先对其进行拷贝。 -It is useful to remember which operations on arrays mutate them, and which don't. For example, `push`, `pop`, `reverse`, and `sort` will mutate the original array, but `slice`, `filter`, and `map` will create a new one. +记住数组上的哪些操作会修改原始数组,将会非常有用。例如,`push`、`pop`、`reverse` 和`sort` 会改变原始数组,但 `slice`、`filter` 和 `map` 则会创建一个新数组。 From 29b3b1616bbb387e4ac9f396988ff6c22380d08d Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:41:02 +0800 Subject: [PATCH 02/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 09a4321786..6d785bb52b 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -6,7 +6,7 @@ translators: -一些 JavaScript 函数是“纯”的。纯函数仅仅执行计算,不做其他事情。将组件严格编写为纯函数,你可以避免随着代码库的增长而出现一整类令人困扰的 bugs 和不可预测的行为。但为了获得这些好处,你需要遵循一些规则。 +一些 JavaScript 函数是“纯”的。纯函数仅仅执行计算,不做其他事情。通过将组件严格编写为纯函数,你可以避免一些随着代码库的增长而出现的、令人困扰的 bugs 和不可预测的行为。但为了获得这些好处,你需要遵循一些规则。 From d54b4e381686d7ed8fbda7ccd660798ce3772c74 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:43:14 +0800 Subject: [PATCH 03/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 6d785bb52b..4effeea287 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -13,7 +13,7 @@ translators: * 纯函数是什么,以及它如何帮助你避免 bugs -* 如何将更改置于渲染阶段外,以保持组件的纯净 +* 如何将数据变更与渲染过程分离,以保持组件的纯净 * 如何使用严格模式找到组件中的错误 From 84313ce51b26ef27dc7566c0b732222634dad4af Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:43:21 +0800 Subject: [PATCH 04/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 4effeea287..d33bb2e99c 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -33,7 +33,7 @@ translators: 若 x = 3y = 6。 永远如此。 -若 x = 3,那么 y 不会受当前时段或股市状况影响,而等于 9–12.5。 +若 x = 3,那么 y 并不会因为时间或股市的影响,而有时等于 9–12.5。 若 y = 2xx = 3, 那么 y _永远_ 等于 6. From 341ffa55744d96a03aa8b587a84ddf004211dc95 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:43:29 +0800 Subject: [PATCH 05/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index d33bb2e99c..e82943ba25 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -47,7 +47,7 @@ function double(number) { 上述例子中,`double()` 就是一个**纯函数**。如果你传入 `3` ,它将总是返回 `6` 。 -React 便围绕着这个概念进行设计。它假设你编写的所有组件都是纯函数,对于相同的输入,必须总是返回相同的 JSX。 +React 便围绕着这个概念进行设计。**React 假设你编写的所有组件都是纯函数。**也就是说,对于相同的输入,你所编写的 React 组件必须总是返回相同的 JSX。 From f4fe022d2c53045757ebbfaea842ac135979a3a2 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:43:41 +0800 Subject: [PATCH 06/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index e82943ba25..c5c7d3ecea 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -87,7 +87,7 @@ export default function App() { -## 副作用:(无)意识后果 {#side-effects-unintended-consequences} +## 副作用:(非)预期的后果 {#side-effects-unintended-consequences} React 的渲染过程必须始终是纯的。组件应该只*返回* 它们的 JSX,而不*改变* 在渲染前存在的任何对象或变量——这将会使它们变得不纯! From 0b237ab0228c504ad28df1d364f53bb6bf8e33dc Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:44:10 +0800 Subject: [PATCH 07/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index c5c7d3ecea..ded8a9164e 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -155,7 +155,7 @@ export default function TeaSet() { React 提供了“严格模式”,在严格模式下开发时,它将两次调用组件函数。**通过重复调用组件函数,严格模式有助于找到违反这些规则的组件**。 -我们注意到,原始示例显示的是“Guest #2”、“Guest #4”和“Guest #6”,而不是“Guest #1”、“Guest #2”和“Guest #3”。原来的函数是不纯的,调用它两次破坏了它。但对于固定的纯函数版本,即使调用该函数两次也能得到正确结果。**纯函数仅仅执行计算,因此两次调用它们不会改变任何东西**——就像两次调用 `double(2)` 不会改变返回的内容,两次求解 y = 2x 不会改变 y 的值一样。相同的输入,总是返回相同的输出。 +我们注意到,原始示例显示的是“Guest #2”、“Guest #4”和“Guest #6”,而不是“Guest #1”、“Guest #2”和“Guest #3”。原来的函数是不纯的,因此调用它两次就出现了问题。但对于修复后的纯函数版本,即使调用该函数两次也能得到正确结果。**纯函数仅仅执行计算,因此调用它们两次不会改变任何东西**——就像两次调用 `double(2)` 不会改变返回的内容,两次求解 y = 2x 不会改变 y 的值一样。相同的输入,总是返回相同的输出。 严格模式在生产环境下会失效,因此它不会降低应用程序的速度。如需引入严格模式,你可以将根组件包装到 `` 中。一些框架会默认这样做。 From a16990abbcc013c83db50a883b92425ee4fc1594 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:44:24 +0800 Subject: [PATCH 08/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index ded8a9164e..beaea325ff 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -157,7 +157,7 @@ React 提供了“严格模式”,在严格模式下开发时,它将两次 我们注意到,原始示例显示的是“Guest #2”、“Guest #4”和“Guest #6”,而不是“Guest #1”、“Guest #2”和“Guest #3”。原来的函数是不纯的,因此调用它两次就出现了问题。但对于修复后的纯函数版本,即使调用该函数两次也能得到正确结果。**纯函数仅仅执行计算,因此调用它们两次不会改变任何东西**——就像两次调用 `double(2)` 不会改变返回的内容,两次求解 y = 2x 不会改变 y 的值一样。相同的输入,总是返回相同的输出。 -严格模式在生产环境下会失效,因此它不会降低应用程序的速度。如需引入严格模式,你可以将根组件包装到 `` 中。一些框架会默认这样做。 +严格模式在生产环境下不生效,因此它不会降低应用程序的速度。如需引入严格模式,你可以用 `` 包裹根组件。一些框架会默认这样做。 From 5fd588f49059dc77f7ef1d3f660d6e89a00b1614 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:44:54 +0800 Subject: [PATCH 09/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index beaea325ff..6d0753f9c6 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -117,7 +117,7 @@ export default function TeaSet() { -该组件正在读写在其外部声明的 `guest` 变量。这意味着**多次调用这个组件会产生不同的 JSX!**并且,如果其他组件读取 `guest` ,它们也会产生不同的 JSX,其结果取决于它们何时被渲染!这是不可预测的。 +该组件正在读写在其外部声明的 `guest` 变量。这意味着**多次调用这个组件会产生不同的 JSX!**并且,如果 _其他_ 组件读取 `guest` ,它们也会产生不同的 JSX,其结果取决于它们何时被渲染!这是不可预测的。 回到我们的公式 y = 2x ,现在即使 x = 2 ,我们也不能相信 y = 4 。我们的测试可能会失败,我们的用户可能会感到困扰,飞机可能会从天空坠毁——你将看到这会引发多么扑朔迷离的 bugs! From 2c678a84bde0ccda3ae798435e89c7ad7880df65 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:45:48 +0800 Subject: [PATCH 10/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 6d0753f9c6..e9919f74df 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -165,7 +165,7 @@ React 提供了“严格模式”,在严格模式下开发时,它将两次 上述例子里,问题出在渲染过程中,组件改变了 *preexisting* 变量的值。这种行为通常被称为 **“mutation”** ,以使其听起来更可怕。纯函数不会改变函数作用域外的变量或在函数调用前创建的对象——这使它们变得不纯! -但是,**在渲染时更改你 *刚刚* 创建的变量和对象完全没问题**。在本例中,你创建一个 `[]` 数组,将其分配给一个 `cups` 变量,然后 `push` 一打 cups 进去: +但是,**你完全可以在渲染时更改你 *刚刚* 创建的变量和对象**。在本例中,你创建一个 `[]` 数组,将其分配给一个 `cups` 变量,然后 `push` 一打 cups 进去: From d00ceb831da7ca564c6c693e03e6070c6d1b4a9f Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:46:40 +0800 Subject: [PATCH 11/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index e9919f74df..f303d63e56 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -185,7 +185,7 @@ export default function TeaGathering() { -如果 `cups` 变量或 `[]` 数组是在 `TeaGathering` 函数之外创建的,这将是一个巨大的问题!你调用的数组 push 方法将更改*预先存在的* 对象。 +如果 `cups` 变量或 `[]` 数组是在 `TeaGathering` 函数之外创建的,这将是一个巨大的问题!因为如果那样的话,你调用的数组 push 方法将更改 *预先存在的* 对象。 但是,这里不会有影响,因为每次渲染时,你都是在 `TeaGathering` 函数内部创建的它们。 `TeaGathering` 之外的代码不会知道发生了什么。这就被称为 **“局部 mutation”** ——如同藏在组件里的小秘密。 From e6b42a2c54f78de6892ec248ff4719e7f272df7e Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:46:48 +0800 Subject: [PATCH 12/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index f303d63e56..b9ca18b792 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -189,7 +189,7 @@ export default function TeaGathering() { 但是,这里不会有影响,因为每次渲染时,你都是在 `TeaGathering` 函数内部创建的它们。 `TeaGathering` 之外的代码不会知道发生了什么。这就被称为 **“局部 mutation”** ——如同藏在组件里的小秘密。 -## 哪里可能引发副作用 {#where-you-can-cause-side-effects} +## 哪些地方 _可能_ 引发副作用 {#where-you-can-cause-side-effects} 函数式编程在很大程度上依赖于纯函数,但某些事物在特定情况下不得不发生改变。这是编程的要义!这些变动——更新屏幕、启动动画、更改数据——被称为**副作用**。它们是 _“额外”_ 发生的事情,与渲染过程无关。 From 24240a33783a6273d8757e6ccb172117ac4afe3c Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:47:15 +0800 Subject: [PATCH 13/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index b9ca18b792..ae9e8bd588 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -191,7 +191,7 @@ export default function TeaGathering() { ## 哪些地方 _可能_ 引发副作用 {#where-you-can-cause-side-effects} -函数式编程在很大程度上依赖于纯函数,但某些事物在特定情况下不得不发生改变。这是编程的要义!这些变动——更新屏幕、启动动画、更改数据——被称为**副作用**。它们是 _“额外”_ 发生的事情,与渲染过程无关。 +函数式编程在很大程度上依赖于纯函数,但 _某些事物_ 在特定情况下不得不发生改变。这是编程的要义!这些变动——更新屏幕、启动动画、更改数据——被称为**副作用**。它们是 _“额外”_ 发生的事情,与渲染过程无关。 在 React 中,**副作用通常属于[事件处理程序](/learn/responding-to-events)。** 事件处理程序是 React 在你执行某些操作——例如,当单击按钮时——运行的函数。即使事件处理程序是在你的组件*内部* 定义的,它们也不会在渲染期间运行! **因此事件处理程序不需要是纯函数。** From 01e0163fabdb03d676e8b7a1568c983e214391db Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:47:32 +0800 Subject: [PATCH 14/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index ae9e8bd588..972c0bffbd 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -193,7 +193,7 @@ export default function TeaGathering() { 函数式编程在很大程度上依赖于纯函数,但 _某些事物_ 在特定情况下不得不发生改变。这是编程的要义!这些变动——更新屏幕、启动动画、更改数据——被称为**副作用**。它们是 _“额外”_ 发生的事情,与渲染过程无关。 -在 React 中,**副作用通常属于[事件处理程序](/learn/responding-to-events)。** 事件处理程序是 React 在你执行某些操作——例如,当单击按钮时——运行的函数。即使事件处理程序是在你的组件*内部* 定义的,它们也不会在渲染期间运行! **因此事件处理程序不需要是纯函数。** +在 React 中,**副作用通常属于 [事件处理程序](/learn/responding-to-events)。** 事件处理程序是 React 在你执行某些操作——例如,当单击按钮时——运行的函数。即使事件处理程序是在你的组件 *内部* 定义的,它们也不会在渲染期间运行! **因此事件处理程序不需要是纯函数。** 如果你用尽一切选项,仍无法为副作用找到合适的事件处理程序的话,你还可以调用组件中的 [`useEffect`](/reference/useeffect) 方法将其附加到返回的 JSX 中。这告诉 React 在渲染结束后执行它。**然而,这种方法应该是你最后的手段。** From da02e234e9491a76e78a66d11f4c308f4b69e428 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:47:50 +0800 Subject: [PATCH 15/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 972c0bffbd..762105c887 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -205,7 +205,7 @@ export default function TeaGathering() { * 你的组件可以在不同的环境下运行——例如,在服务器上!由于它们针对相同的输入,总是返回相同的结果,因此一个组件可以满足多个用户请求。 * 对于输入未更改的组件,你可以[跳过渲染](/learn/skiping-unchanged-trees)来提高性能。这是安全的做法,因为纯函数总是返回相同的结果,所以它们可以安全地缓存。 -* 如果在渲染深层组件树的过程中某些数据发生了变化,React 可以重新开始渲染,而不会浪费时间完成过时的渲染。纯函数使得它可以随时安全地停止计算。 +* 如果在渲染深层组件树的过程中,某些数据发生了变化,React 可以重新开始渲染,而不会浪费时间完成过时的渲染。纯粹性使得它随时可以安全地停止计算。 我们正在构建的每个 React 新功能都利用到了纯函数。从数据获取到动画再到性能,保持组件的纯净可以充分释放 React 范式的能力。 From e22f148306f5a9c995b1063f4bfdc7f7b8c9dd80 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:48:04 +0800 Subject: [PATCH 16/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 762105c887..e5aaadcbe8 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -217,7 +217,7 @@ export default function TeaGathering() { * **只负责自己的任务。** 不应更改渲染前存在的任何对象或变量。 * **输入相同,则输出相同。** 给定相同的输入,组件应该总是返回相同的 JSX。 * 渲染随时可能发生,因此组件不应依赖于彼此的渲染顺序。 -* 你不应该改变组件用于渲染的输入。这包括 props、state 和 context。如需更新界面,["设置"状态](reacting-to-input-with-state) 而不是改变预先存在的对象。 +* 你不应该改变组件用于渲染的任何输入。这包括 props、state 和 context。通过 [“设置” state](reacting-to-input-with-state) 来更新界面,而不要改变预先存在的对象。 * 努力在你返回的 JSX 中表达你的组件逻辑。当你需要“改变事物”时,你通常希望在事件处理程序中进行。作为最后的手段,你可以使用 `useEffect`。 * 编写纯函数需要一些练习,但它充分释放了 React 范式的能力。 From f08b9e166d3cab242659c5eec0730b839c959911 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:48:34 +0800 Subject: [PATCH 17/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index e5aaadcbe8..154dfcb85f 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -229,7 +229,7 @@ export default function TeaGathering() { ### 修复坏掉的时钟 -该组件尝试将 `

` 的 CSS 类设置为从午夜到早上 6 小时的时间为 `"night"`,而在所有其他时间为 `"day"`。但它不起作用。你能修复这个组件吗? +该组件尝试在午夜到早上 6 点期间,将 `

` 的 CSS 类设置为 `"night"`,而在其他时间都设置为 `"day"`。但它不起作用。你能修复这个组件吗? 你可以临时更改计算机的时区来验证你的解决方案是否有效。当前时间位于午夜至早上六点之间时,时钟应该有相反的颜色! From 91866a4b08d5afdc8487e872cb66e274432ef428 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:48:52 +0800 Subject: [PATCH 18/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 154dfcb85f..b46b4771dd 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -235,7 +235,7 @@ export default function TeaGathering() { -渲染是一种*计算过程* ,它不应该试图“做”其他事情。你能用其他方式表达和这一样的想法吗? +渲染是一种 *计算过程* ,它不应该试图“做”其他事情。你能用其他方式表达这一思想吗? From e4e17bae632520f1aaabd212de5333af526b1ba5 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:49:07 +0800 Subject: [PATCH 19/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index b46b4771dd..50b41da3b0 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -299,7 +299,7 @@ body > * { -你可以计算 className,并将其包含在渲染的输出中,以此实现对组件的修复: +你可以计算 `className`,并将其包含在渲染的输出中,以此实现对组件的修复: From e426dfc2adde8aac672b403a0707adc711f563dd Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:49:31 +0800 Subject: [PATCH 20/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 50b41da3b0..a9d648ac25 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -673,7 +673,7 @@ li { -请注意,每当时钟更新时,“Create Story” 都会被添加*两次*。这暗示我们在渲染过程中发生了 mutation——严格模式调用组件两次可以使这些问题更加明显。 +请注意,每当时钟更新时,“Create Story”都会被添加 *两次*。这暗示我们在渲染过程中发生了 mutation——严格模式调用两次组件,可以使这些问题更加明显。 `StoryTray` 的功能不纯。通过在接收到的 `stories` 数组(一个 prop!)上调用 `push` 方法,它正改变着一个在 `StoryTray` 渲染*之前* 创建的对象。这使得它有问题并且难以预测。 From cf18cfc016181b8aace94044f356e9d1048c8fcd Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:49:41 +0800 Subject: [PATCH 21/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index a9d648ac25..abb42c7cdf 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -675,7 +675,7 @@ li { 请注意,每当时钟更新时,“Create Story”都会被添加 *两次*。这暗示我们在渲染过程中发生了 mutation——严格模式调用两次组件,可以使这些问题更加明显。 -`StoryTray` 的功能不纯。通过在接收到的 `stories` 数组(一个 prop!)上调用 `push` 方法,它正改变着一个在 `StoryTray` 渲染*之前* 创建的对象。这使得它有问题并且难以预测。 +`StoryTray` 的功能不纯。通过在接收到的 `stories` 数组(一个 prop!)上调用 `push` 方法,它正改变着一个在 `StoryTray` 渲染 *之前* 创建的对象。这使得它有问题并且难以预测。 最简单的解决方案是完全不碰数组,单独渲染 “Create Story”: From a349a0a1f4fc83f2c908c757a36bcd136b47d110 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:49:51 +0800 Subject: [PATCH 22/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index abb42c7cdf..c538b08ec9 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -677,7 +677,7 @@ li { `StoryTray` 的功能不纯。通过在接收到的 `stories` 数组(一个 prop!)上调用 `push` 方法,它正改变着一个在 `StoryTray` 渲染 *之前* 创建的对象。这使得它有问题并且难以预测。 -最简单的解决方案是完全不碰数组,单独渲染 “Create Story”: +最简单的解决方案是完全不碰数组,单独渲染“Create Story”: From 1ad4e81ed59633fe9bf319727db05ed207562a2e Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:50:03 +0800 Subject: [PATCH 23/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index c538b08ec9..4f4f811673 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -761,7 +761,7 @@ li { -或者,你可以在将 item 项 push 进去之前创建一个 _新_ 数组(通过复制现有数组): +或者,你可以在 push 之前创建一个 _新_ 数组(通过复制现有数组): From 3091cd136050b1fe219d5cb2a4822b98325f02a5 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:50:19 +0800 Subject: [PATCH 24/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 4f4f811673..c4e18cc2a0 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -855,7 +855,7 @@ li { 这使你的 mutation 保持在局部,并使你的渲染函数保持纯净。但你仍然需要小心:例如,当你想要更改数组的任意项时,必须先对其进行拷贝。 -记住数组上的哪些操作会修改原始数组,将会非常有用。例如,`push`、`pop`、`reverse` 和`sort` 会改变原始数组,但 `slice`、`filter` 和 `map` 则会创建一个新数组。 +记住数组上的哪些操作会修改原始数组、哪些不会,这非常有帮助。例如,`push`、`pop`、`reverse` 和 `sort` 会改变原始数组,但 `slice`、`filter` 和 `map` 则会创建一个新数组。 From e0d939a397a9eda3ab829531d2c9958420443940 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:50:39 +0800 Subject: [PATCH 25/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index c4e18cc2a0..a4bbb6e559 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -121,7 +121,7 @@ export default function TeaSet() { 回到我们的公式 y = 2x ,现在即使 x = 2 ,我们也不能相信 y = 4 。我们的测试可能会失败,我们的用户可能会感到困扰,飞机可能会从天空坠毁——你将看到这会引发多么扑朔迷离的 bugs! -你可以[将 `guest` 作为 prop 传入](/learn/passing-props-to-a-component)来修复此组件: +你可以 [将 `guest` 作为 prop 传入](/learn/passing-props-to-a-component) 来修复此组件: From 5bf8829d9e80adf9d130a586a9c901d3d0c6ffbc Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:52:35 +0800 Subject: [PATCH 26/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index a4bbb6e559..dc1e80ce59 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -163,7 +163,7 @@ React 提供了“严格模式”,在严格模式下开发时,它将两次 ### 局部 mutation:组件的小秘密 {#local-mutation-your-components-little-secret} -上述例子里,问题出在渲染过程中,组件改变了 *preexisting* 变量的值。这种行为通常被称为 **“mutation”** ,以使其听起来更可怕。纯函数不会改变函数作用域外的变量或在函数调用前创建的对象——这使它们变得不纯! +上述例子里,问题出在渲染过程中,组件改变了 *预先存在的* 变量的值。为了让它听起来更可怕一点,我们将这种现象称为 **突变(mutation)** 。纯函数不会改变函数作用域外的变量、或在函数调用前创建的对象——这使函数变得不纯! 但是,**你完全可以在渲染时更改你 *刚刚* 创建的变量和对象**。在本例中,你创建一个 `[]` 数组,将其分配给一个 `cups` 变量,然后 `push` 一打 cups 进去: From e1fe09c8c84b6bd6d974f3b362a3c17d8d925eb7 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 11:58:16 +0800 Subject: [PATCH 27/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index dc1e80ce59..c0b626b1e5 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -151,7 +151,7 @@ export default function TeaSet() { 尽管你可能还没有全部使用过它们,但在 React 中,你可以在渲染时读取三种输入:[props](/learn/passing-props-to-a-component), [state](/learn/state-a-components-memory), 和 [context](/learn/passing-data-deeply-with-context)。你应该始终将这些输入视为只读。 -当你想根据用户输入更改某些内容时,你应该[设置状态](/learn/state-a-components-memory)而不是写入变量。当你的组件正在渲染时,你永远不应该改变预先存在的变量或对象。 +当你想根据用户输入 *更改* 某些内容时,你应该 [设置状态](/learn/state-a-components-memory) ,而不是写入变量。当你的组件正在渲染时,你永远不应该改变预先存在的变量或对象。 React 提供了“严格模式”,在严格模式下开发时,它将两次调用组件函数。**通过重复调用组件函数,严格模式有助于找到违反这些规则的组件**。 From 145fc04e1aa40399eb2715f839084770c47f5a46 Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 12:01:16 +0800 Subject: [PATCH 28/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index c0b626b1e5..0bcde2c17f 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -153,7 +153,7 @@ export default function TeaSet() { 当你想根据用户输入 *更改* 某些内容时,你应该 [设置状态](/learn/state-a-components-memory) ,而不是写入变量。当你的组件正在渲染时,你永远不应该改变预先存在的变量或对象。 -React 提供了“严格模式”,在严格模式下开发时,它将两次调用组件函数。**通过重复调用组件函数,严格模式有助于找到违反这些规则的组件**。 +React 提供了“严格模式”,在严格模式下开发时,它将会调用每个组件函数两次。**通过重复调用组件函数,严格模式有助于找到违反这些规则的组件。** 我们注意到,原始示例显示的是“Guest #2”、“Guest #4”和“Guest #6”,而不是“Guest #1”、“Guest #2”和“Guest #3”。原来的函数是不纯的,因此调用它两次就出现了问题。但对于修复后的纯函数版本,即使调用该函数两次也能得到正确结果。**纯函数仅仅执行计算,因此调用它们两次不会改变任何东西**——就像两次调用 `double(2)` 不会改变返回的内容,两次求解 y = 2x 不会改变 y 的值一样。相同的输入,总是返回相同的输出。 From 8ba5490569e5c601e71c9f8997d2796a8eedb97e Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Fri, 10 Dec 2021 12:08:11 +0800 Subject: [PATCH 29/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 0bcde2c17f..3b87b75e64 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -149,7 +149,7 @@ export default function TeaSet() { -尽管你可能还没有全部使用过它们,但在 React 中,你可以在渲染时读取三种输入:[props](/learn/passing-props-to-a-component), [state](/learn/state-a-components-memory), 和 [context](/learn/passing-data-deeply-with-context)。你应该始终将这些输入视为只读。 +尽管你可能还没使用过,但在 React 中,你可以在渲染时读取三种输入:[props](/learn/passing-props-to-a-component), [state](/learn/state-a-components-memory), 和 [context](/learn/passing-data-deeply-with-context)。你应该始终将这些输入视为只读。 当你想根据用户输入 *更改* 某些内容时,你应该 [设置状态](/learn/state-a-components-memory) ,而不是写入变量。当你的组件正在渲染时,你永远不应该改变预先存在的变量或对象。 From a8eacae5e7d7525a68b3e25a3857be85dce8143a Mon Sep 17 00:00:00 2001 From: 7ooz <71685145+7ooz@users.noreply.github.com> Date: Thu, 6 Jan 2022 23:26:30 +0800 Subject: [PATCH 30/32] Update beta/src/pages/learn/keeping-components-pure.md Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- beta/src/pages/learn/keeping-components-pure.md | 1 + 1 file changed, 1 insertion(+) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index 9b350bc701..0bed3ee6c1 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -2,6 +2,7 @@ title: 保持组件的纯净 translators: - 7ooz + - Hyuain --- From e5cd6d81a0bfc5c983b2a9979b362761ac00e10f Mon Sep 17 00:00:00 2001 From: QiChang Li Date: Fri, 27 May 2022 23:24:33 +0800 Subject: [PATCH 31/32] Apply suggestions from code review Co-authored-by: Harvey Zhang <57085147+Hyuain@users.noreply.github.com> --- .../pages/learn/keeping-components-pure.md | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index f06b4618ce..aad57c4d84 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -7,32 +7,32 @@ translators: -部分 JavaScript 函数是 **纯粹** 的,通常被称为纯函数。纯函数仅仅执行计算,不做其他事情。通过将组件严格编写为纯函数,你可以避免一些随着代码库的增长而出现的、令人困扰的 bugs 和不可预测的行为。但为了获得这些好处,你需要遵循一些规则。 +部分 JavaScript 函数是 **纯粹** 的,这类函数通常被称为纯函数。纯函数仅执行计算操作,不做其他操作。你可以通过将组件按纯函数严格编写,以避免一些随着代码库的增长而出现的、令人困扰的 bug 以及不可预测的行为。但为了获得这些好处,你需要遵循一些规则。 -* 纯函数是什么,以及它如何帮助你避免 bugs -* 如何将数据变更与渲染过程分离,以保持组件的纯净 -* 如何使用严格模式找到组件中的错误 +* 纯函数是什么,以及它如何帮助你避免 bug +* 如何将数据变更与渲染过程分离,以保持组件的纯粹 +* 如何使用严格模式发现组件中的错误 ## 纯函数:组件作为公式 {/*purity-components-as-formulas*/} -在计算机科学中(尤其是函数式编程的世界中),一个[纯函数](https://wikipedia.org/wiki/Pure_function)具有如下特征: +在计算机科学中(尤其是函数式编程的世界中),[纯函数](https://wikipedia.org/wiki/Pure_function) 通常具有如下特征: -* **只负责自己的任务**。它不会更改在该函数调用前便存在的对象或变量。 +* **只负责自己的任务**。它不会更改在该函数调用前,就已存在的对象或变量。 * **输入相同,则输出相同**。给定相同的输入,纯函数应总是返回相同的结果。 -你也许已经熟悉了纯函数的一个例子:数学中的公式。 +举个你非常熟悉的纯函数示例:数学中的公式。 考虑如下数学公式:y = 2x。 -若 x = 2y = 4。 永远如此。 +若 x = 2y = 4。永远如此。 -若 x = 3y = 6。 永远如此。 +若 x = 3y = 6。永远如此。 若 x = 3,那么 y 并不会因为时间或股市的影响,而有时等于 9–12.5。 @@ -46,9 +46,9 @@ function double(number) { } ``` -上述例子中,`double()` 就是一个**纯函数**。如果你传入 `3` ,它将总是返回 `6` 。 +上述例子中,`double()` 就是一个 **纯函数**。如果你传入 `3` ,它将总是返回 `6` 。 -React 便围绕着这个概念进行设计。**React 假设你编写的所有组件都是纯函数。**也就是说,对于相同的输入,你所编写的 React 组件必须总是返回相同的 JSX。 +React 便围绕着这个概念进行设计。**React 假设你编写的所有组件都是纯函数**。也就是说,对于相同的输入,你所编写的 React 组件必须总是返回相同的 JSX。 @@ -84,13 +84,13 @@ export default function App() { 就像数学公式一样。 -你可以把你的组件当作食谱:如果你遵循它们,并且在烹饪过程中不引入新食材,你每次都会得到相同的菜肴。那道“菜肴”就是组件用于 React [渲染](render-and-commit)的 JSX。 +你可以把你的组件当作食谱:如果你遵循它们,并且在烹饪过程中不引入新食材,你每次都会得到相同的菜肴。那这道 “菜肴” 就是组件用于 React [渲染](render-and-commit) 的 JSX。 -## 副作用:(非)预期的后果 {/*side-effects-unintended-consequences*/} +## 副作用:(不符合)预期的后果 {/*side-effects-unintended-consequences*/} -React 的渲染过程必须始终是纯的。组件应该只*返回* 它们的 JSX,而不*改变* 在渲染前存在的任何对象或变量——这将会使它们变得不纯! +React 的渲染过程必须自始至终是纯粹的。组件应该只 **返回** 它们的 JSX,而不 **改变** 在渲染前,就已存在的任何对象或变量 — 这将会使它们变得不纯粹! 以下是违反这一规则的组件示例: @@ -118,7 +118,7 @@ export default function TeaSet() { -该组件正在读写在其外部声明的 `guest` 变量。这意味着**多次调用这个组件会产生不同的 JSX!**并且,如果 _其他_ 组件读取 `guest` ,它们也会产生不同的 JSX,其结果取决于它们何时被渲染!这是不可预测的。 +该组件正在读写其外部声明的 `guest` 变量。这意味着 **多次调用这个组件会产生不同的 JSX**!并且,如果 **其他** 组件读取 `guest` ,它们也会产生不同的 JSX,其结果取决于它们何时被渲染!这是无法预测的。 回到我们的公式 y = 2x ,现在即使 x = 2 ,我们也不能相信 y = 4 。我们的测试可能会失败,我们的用户可能会感到困扰,飞机可能会从天空坠毁——你将看到这会引发多么扑朔迷离的 bugs! @@ -144,19 +144,19 @@ export default function TeaSet() { -现在你的组件就是纯的了,因为它返回的 JSX 只依赖于 `guest` prop。 +现在你的组件就是纯粹的,因为它返回的 JSX 只依赖于 `guest` prop。 一般来说,你不应该期望你的组件以任何特定的顺序被渲染。调用 y = 5xy = 2x 的先后顺序并不重要:这两个公式相互独立。同样地,每个组件也应该“独立思考”,而不是在渲染过程中试图与其他组件协调,或者依赖于其他组件。渲染过程就像是一场学校考试:每个组件都应该自己计算 JSX! -尽管你可能还没使用过,但在 React 中,你可以在渲染时读取三种输入:[props](/learn/passing-props-to-a-component), [state](/learn/state-a-components-memory), 和 [context](/learn/passing-data-deeply-with-context)。你应该始终将这些输入视为只读。 +尽管你可能还没使用过,但在 React 中,你可以在渲染时读取三种输入:[props](/learn/passing-props-to-a-component),[state](/learn/state-a-components-memory) 和 [context](/learn/passing-data-deeply-with-context)。你应该始终将这些输入视为只读。 -当你想根据用户输入 *更改* 某些内容时,你应该 [设置状态](/learn/state-a-components-memory) ,而不是写入变量。当你的组件正在渲染时,你永远不应该改变预先存在的变量或对象。 +当你想根据用户输入 *更改* 某些内容时,你应该 [设置状态](/learn/state-a-components-memory),而不是直接写入变量。当你的组件正在渲染时,你永远不应该改变预先存在的变量或对象。 -React 提供了“严格模式”,在严格模式下开发时,它将会调用每个组件函数两次。**通过重复调用组件函数,严格模式有助于找到违反这些规则的组件。** +React 提供了 “严格模式”,在严格模式下开发时,它将会调用每个组件函数两次。**通过重复调用组件函数,严格模式有助于找到违反这些规则的组件**。 -我们注意到,原始示例显示的是“Guest #2”、“Guest #4”和“Guest #6”,而不是“Guest #1”、“Guest #2”和“Guest #3”。原来的函数是不纯的,因此调用它两次就出现了问题。但对于修复后的纯函数版本,即使调用该函数两次也能得到正确结果。**纯函数仅仅执行计算,因此调用它们两次不会改变任何东西**——就像两次调用 `double(2)` 不会改变返回的内容,两次求解 y = 2x 不会改变 y 的值一样。相同的输入,总是返回相同的输出。 +我们注意到,原始示例显示的是 “Guest #2”、“Guest #4” 和 “Guest #6”,而不是 “Guest #1”、“Guest #2” 和 “Guest #3”。原来的函数并不纯粹,因此调用它两次就出现了问题。但对于修复后的纯函数版本,即使调用该函数两次也能得到正确结果。**纯函数仅仅执行计算,因此调用它们两次不会改变任何东西** — 就像两次调用 `double(2)` 并不会改变返回值,两次求解 y = 2x 不会改变 y 的值一样。相同的输入,总是返回相同的输出。 严格模式在生产环境下不生效,因此它不会降低应用程序的速度。如需引入严格模式,你可以用 `` 包裹根组件。一些框架会默认这样做。 @@ -164,9 +164,9 @@ React 提供了“严格模式”,在严格模式下开发时,它将会调 ### 局部 mutation:组件的小秘密 {/*local-mutation-your-components-little-secret*/} -上述例子里,问题出在渲染过程中,组件改变了 *预先存在的* 变量的值。为了让它听起来更可怕一点,我们将这种现象称为 **突变(mutation)** 。纯函数不会改变函数作用域外的变量、或在函数调用前创建的对象——这使函数变得不纯! +上述示例的问题出在渲染过程中,组件改变了 **预先存在的** 变量的值。为了让它听起来更可怕一点,我们将这种现象称为 **突变(mutation)** 。纯函数不会改变函数作用域外的变量、或在函数调用前创建的对象 — 这会使函数变得不纯粹! -但是,**你完全可以在渲染时更改你 *刚刚* 创建的变量和对象**。在本例中,你创建一个 `[]` 数组,将其分配给一个 `cups` 变量,然后 `push` 一打 cups 进去: +但是,**你完全可以在渲染时更改你 *刚刚* 创建的变量和对象**。在本示例中,你创建一个 `[]` 数组,将其分配给一个 `cups` 变量,然后 `push` 一打 cup 进去: @@ -186,35 +186,35 @@ export default function TeaGathering() { -如果 `cups` 变量或 `[]` 数组是在 `TeaGathering` 函数之外创建的,这将是一个巨大的问题!因为如果那样的话,你调用的数组 push 方法将更改 *预先存在的* 对象。 +如果 `cups` 变量或 `[]` 数组是在 `TeaGathering` 函数之外创建的,这将是一个很大的问题!因为如果那样的话,当你调用数组的 push 方法时,就会更改 **预先存在的** 对象。 -但是,这里不会有影响,因为每次渲染时,你都是在 `TeaGathering` 函数内部创建的它们。 `TeaGathering` 之外的代码不会知道发生了什么。这就被称为 **“局部 mutation”** ——如同藏在组件里的小秘密。 +但是,这里不会有影响,因为每次渲染时,你都是在 `TeaGathering` 函数内部创建的它们。`TeaGathering` 之外的代码并不会知道发生了什么。这就被称为 **“局部 mutation”** — 如同藏在组件里的小秘密。 -## 哪些地方 _可能_ 引发副作用 {/*where-you-can-cause-side-effects*/} +## 哪些地方 **可能** 引发副作用 {/*where-you-can-cause-side-effects*/} -函数式编程在很大程度上依赖于纯函数,但 _某些事物_ 在特定情况下不得不发生改变。这是编程的要义!这些变动——更新屏幕、启动动画、更改数据——被称为**副作用**。它们是 _“额外”_ 发生的事情,与渲染过程无关。 +函数式编程在很大程度上依赖于纯函数,但 **某些事物** 在特定情况下不得不发生改变。这是编程的要义!这些变动包括更新屏幕、启动动画、更改数据等,它们被称为 **副作用**。它们是 **“额外”** 发生的事情,与渲染过程无关。 -在 React 中,**副作用通常属于 [事件处理程序](/learn/responding-to-events)。** 事件处理程序是 React 在你执行某些操作——例如,当单击按钮时——运行的函数。即使事件处理程序是在你的组件 *内部* 定义的,它们也不会在渲染期间运行! **因此事件处理程序不需要是纯函数。** +在 React 中,**副作用通常属于 [事件处理程序](/learn/responding-to-events)**。事件处理程序是 React 在你执行某些操作(如单击按钮)时运行的函数。即使事件处理程序是在你的组件 **内部** 定义的,它们也不会在渲染期间运行! **因此事件处理程序无需是纯函数**。 -如果你用尽一切选项,仍无法为副作用找到合适的事件处理程序的话,你还可以调用组件中的 [`useEffect`](/apis/useeffect) 方法将其附加到返回的 JSX 中。这告诉 React 在渲染结束后执行它。**然而,这种方法应该是你最后的手段。** +如果你用尽一切办法,仍无法为副作用找到合适的事件处理程序,你还可以调用组件中的 [`useEffect`](/apis/useeffect) 方法将其附加到返回的 JSX 中。这会告诉 React 在渲染结束后执行它。**然而,这种方法应该是你最后的手段**。 如果可能,请尝试仅通过渲染过程来表达你的逻辑。你会惊讶于这能带给你多少好处! -编写纯函数需要一些习惯和纪律。但它也带来了绝妙的机会: +编写纯函数需要遵循一些习惯和规程。但它开启了绝妙的机遇: -* 你的组件可以在不同的环境下运行——例如,在服务器上!由于它们针对相同的输入,总是返回相同的结果,因此一个组件可以满足多个用户请求。 -* 你可以 [跳过渲染](/learn/skiping-unchanged-trees) 那些输入未更改的组件,来提高性能。这是安全的做法,因为纯函数总是返回相同的结果,所以可以安全地缓存它们。 +* 你的组件可以在不同的环境下运行 — 例如,在服务器上!由于它们针对相同的输入,总是返回相同的结果,因此一个组件可以满足多个用户请求。 +* 你可以为那些输入未更改的组件来 [跳过渲染](/learn/skipping-unchanged-trees),以提高性能。这是安全的做法,因为纯函数总是返回相同的结果,所以可以安全地缓存它们。 * 如果在渲染深层组件树的过程中,某些数据发生了变化,React 可以重新开始渲染,而不会浪费时间完成过时的渲染。纯粹性使得它随时可以安全地停止计算。 -我们正在构建的每个 React 新功能都利用到了纯函数。从数据获取到动画再到性能,保持组件的纯净可以充分释放 React 范式的能力。 +我们正在构建的每个 React 新特性都利用到了纯函数。从数据获取到动画再到性能,保持组件的纯粹可以充分释放 React 范式的能力。 -* 一个组件必须是纯的,意味着: +* 一个组件必须是纯粹的,就意味着: * **只负责自己的任务。** 不应更改渲染前存在的任何对象或变量。 * **输入相同,则输出相同。** 给定相同的输入,组件应该总是返回相同的 JSX。 * 渲染随时可能发生,因此组件不应依赖于彼此的渲染顺序。 @@ -228,7 +228,7 @@ export default function TeaGathering() { -### 修复坏掉的时钟 {/*修复坏掉的时钟*/} +### 修复坏掉的时钟 {/*fix-a-broken-clock*/} 该组件尝试在午夜到早上 6 点期间,将 `

` 的 CSS 类设置为 `"night"`,而在其他时间都设置为 `"day"`。但它不起作用。你能修复这个组件吗? @@ -365,9 +365,9 @@ body > * { -### 修复损坏的名片 {/*修复损坏的名片*/} +### 修复损坏的资料 {/*fix-a-broken-profile*/} -两个 `Profile` 组件使用不同的数据并排呈现。在第一张名片上点击“Collapse”折叠,然后点击“Expand”展开它。你会看到两张名片现在显示的是同一个人。这是一个 bug。 +两个 `Profile` 组件使用不同的数据并排呈现。在第一个资料中点击 “Collapse” 折叠,然后点击 “Expand” 展开它。你会看到两个资料现在显示的是同一个人。这是一个 bug。 找出产生 bug 的原因,并修复它。 @@ -474,9 +474,9 @@ h1 { margin: 5px; font-size: 18px; } -问题在于 `Profile` 组件写入了一个预先存在的 `currentPerson` 变量,而 `Header` 和 `Avatar` 组件从中读取了这个变量。这使得*所有三个* 组件都变得不纯并且难以预测。 +问题在于 `Profile` 组件写入了一个预先存在的 `currentPerson` 变量,而 `Header` 和 `Avatar` 组件读取了这个变量。这使得 **三个组件都** 变得不纯粹且难以预测。 -要修复这个 bug,需要删除 `currentPerson` 变量。然后以 props 作为替代,将所有信息从 `Profile` 传递到 `Header` 和 `Avatar` 中。你需要向两个组件添加一个 `person` 属性并将其一直向下传递。 +要修复这个 bug,需要删除 `currentPerson` 变量。同时,通过 props 将所有信息从 `Profile` 传递到 `Header` 和 `Avatar` 中。你需要向两个组件各添加一个 `person` prop,并将其一直向下传递。 @@ -574,9 +574,9 @@ h1 { margin: 5px; font-size: 18px; } -### 修复损坏的故事托盘 {/*修复损坏的故事托盘*/} +### 修复损坏的故事集 {/*fix-a-broken-story-tray*/} -你所在公司的 CEO 要求你在你的在线时钟 app 中添加“故事”,你不能拒绝。你已经编写了一个 `StoryTray` 组件,它接受一个 `stories` 列表,后跟一个 “Create Story” 占位符。 +你所在公司的 CEO 要求你在在线时钟 app 中添加 “故事”,你不能拒绝。你编写了一个 `StoryTray` 组件,它接受一个 `stories` 列表,后跟一个 “Create Story” 占位符。 你在作为 props 的 `stories` 数组末尾 push 了一个假故事来实现 “Create Story” 占位符。但出于某种原因,“Create Story” 出现了不止一次。请修复这个问题。 @@ -674,11 +674,11 @@ li { -请注意,每当时钟更新时,“Create Story”都会被添加 *两次*。这暗示我们在渲染过程中发生了 mutation——严格模式调用两次组件,可以使这些问题更加明显。 +请注意,每当时钟更新时,“Create Story” 都会被添加 **两次**。这暗示我们在渲染过程中发生了 mutation — 严格模式调用两次组件,可以使这些问题更加明显。 -`StoryTray` 的功能不纯。通过在接收到的 `stories` 数组(一个 prop!)上调用 `push` 方法,它正改变着一个在 `StoryTray` 渲染 *之前* 创建的对象。这使得它有问题并且难以预测。 +`StoryTray` 的功能不纯粹。通过在接收到的 `stories` 数组(一个 prop!)上调用 `push` 方法,它正改变着一个在 `StoryTray` 渲染 **之前** 创建的对象。这使得它有问题并且难以预测。 -最简单的解决方案是完全不碰数组,单独渲染“Create Story”: +最简单的解决方案是完全不碰数组,单独渲染 “Create Story”: @@ -762,7 +762,7 @@ li { -或者,你可以在 push 之前创建一个 _新_ 数组(通过复制现有数组): +或者,你可以在 push 之前创建一个 **新** 数组(通过复制现有数组): @@ -854,7 +854,7 @@ li { -这使你的 mutation 保持在局部,并使你的渲染函数保持纯净。但你仍然需要小心:例如,当你想要更改数组的任意项时,必须先对其进行拷贝。 +这使你的 mutation 保持在局部,并使你的渲染函数保持纯粹。但你仍然需要小心:例如,当你想要更改数组的任意项时,必须先对其进行拷贝。 记住数组上的哪些操作会修改原始数组、哪些不会,这非常有帮助。例如,`push`、`pop`、`reverse` 和 `sort` 会改变原始数组,但 `slice`、`filter` 和 `map` 则会创建一个新数组。 From baea4519bf712ef99147edfebf7c0cd81ae23d1b Mon Sep 17 00:00:00 2001 From: QiChang Li Date: Fri, 27 May 2022 23:26:48 +0800 Subject: [PATCH 32/32] Update beta/src/pages/learn/keeping-components-pure.md --- beta/src/pages/learn/keeping-components-pure.md | 1 + 1 file changed, 1 insertion(+) diff --git a/beta/src/pages/learn/keeping-components-pure.md b/beta/src/pages/learn/keeping-components-pure.md index aad57c4d84..53ab1d06d3 100644 --- a/beta/src/pages/learn/keeping-components-pure.md +++ b/beta/src/pages/learn/keeping-components-pure.md @@ -3,6 +3,7 @@ title: 保持组件纯粹 translators: - 7ooz - Hyuain + - QC-L ---