diff --git a/content/docs/lifting-state-up.md b/content/docs/lifting-state-up.md
index 449330cfdc..b7772cad23 100644
--- a/content/docs/lifting-state-up.md
+++ b/content/docs/lifting-state-up.md
@@ -1,6 +1,6 @@
---
id: lifting-state-up
-title: Lifting State Up
+title: 状态提升
permalink: docs/lifting-state-up.html
prev: forms.html
next: composition-vs-inheritance.html
@@ -9,11 +9,11 @@ redirect_from:
- "docs/flux-todo-list.html"
---
-Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor. Let's see how this works in action.
+通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。让我们看看它是如何运作的。
-In this section, we will create a temperature calculator that calculates whether the water would boil at a given temperature.
+在本节中,我们将创建一个用于计算水在给定温度下是否会沸腾的温度计算器。
-We will start with a component called `BoilingVerdict`. It accepts the `celsius` temperature as a prop, and prints whether it is enough to boil the water:
+我们将从一个名为 `BoilingVerdict` 的组件开始,它接受 `celsius` 温度作为一个 prop,并据此打印出该温度是否足以将水煮沸的结果。
```js{3,5}
function BoilingVerdict(props) {
@@ -24,9 +24,9 @@ function BoilingVerdict(props) {
}
```
-Next, we will create a component called `Calculator`. It renders an `` that lets you enter the temperature, and keeps its value in `this.state.temperature`.
+接下来, 我们创建一个名为 `Calculator` 的组件。它渲染一个用于输入温度的 ``,并将其值保存在 `this.state.temperature` 中。
-Additionally, it renders the `BoilingVerdict` for the current input value.
+另外, 它根据当前输入值渲染 `BoilingVerdict` 组件。
```js{5,9,13,17-21}
class Calculator extends React.Component {
@@ -56,13 +56,13 @@ class Calculator extends React.Component {
}
```
-[**Try it on CodePen**](https://codepen.io/gaearon/pen/ZXeOBm?editors=0010)
+[**在 CodePen 上尝试**](https://codepen.io/gaearon/pen/ZXeOBm?editors=0010)
-## Adding a Second Input {#adding-a-second-input}
+## 添加第二个输入框 {#adding-a-second-input}
-Our new requirement is that, in addition to a Celsius input, we provide a Fahrenheit input, and they are kept in sync.
+我们的新需求是,在已有摄氏温度输入框的基础上,我们提供华氏度的输入框,并保持两个输入框的数据同步。
-We can start by extracting a `TemperatureInput` component from `Calculator`. We will add a new `scale` prop to it that can either be `"c"` or `"f"`:
+我们先从 `Calculator` 组件中抽离出 `TemperatureInput` 组件,然后为其添加一个新的 `scale` prop,它可以是 `"c"` 或是 `"f"`:
```js{1-4,19,22}
const scaleNames = {
@@ -95,7 +95,7 @@ class TemperatureInput extends React.Component {
}
```
-We can now change the `Calculator` to render two separate temperature inputs:
+我们现在可以修改 `Calculator` 组件让它渲染两个独立的温度输入框组件:
```js{5,6}
class Calculator extends React.Component {
@@ -110,15 +110,15 @@ class Calculator extends React.Component {
}
```
-[**Try it on CodePen**](https://codepen.io/gaearon/pen/jGBryx?editors=0010)
+[**在 CodePen 上尝试**](https://codepen.io/gaearon/pen/jGBryx?editors=0010)
-We have two inputs now, but when you enter the temperature in one of them, the other doesn't update. This contradicts our requirement: we want to keep them in sync.
+我们现在有了两个输入框,但当你在其中一个输入温度时,另一个并不会更新。这与我们的要求相矛盾:我们希望让它们保持同步。
-We also can't display the `BoilingVerdict` from `Calculator`. The `Calculator` doesn't know the current temperature because it is hidden inside the `TemperatureInput`.
+另外,我们也不能通过 `Calculator` 组件展示 `BoilingVerdict` 组件的渲染结果。因为 `Calculator` 组件并不知道隐藏在 `TemperatureInput` 组件中的当前温度是多少。
-## Writing Conversion Functions {#writing-conversion-functions}
+## 编写转换函数 {#writing-conversion-functions}
-First, we will write two functions to convert from Celsius to Fahrenheit and back:
+首先,我们将编写两个可以在摄氏度与华氏度之间相互转换的函数:
```js
function toCelsius(fahrenheit) {
@@ -130,9 +130,9 @@ function toFahrenheit(celsius) {
}
```
-These two functions convert numbers. We will write another function that takes a string `temperature` and a converter function as arguments and returns a string. We will use it to calculate the value of one input based on the other input.
+上述两个函数仅做数值转换。而我们将编写另一个函数,它接受字符串类型的 `temperature` 和转换函数作为参数并返回一个字符串。我们将使用它来依据一个输入框的值计算出另一个输入框的值。
-It returns an empty string on an invalid `temperature`, and it keeps the output rounded to the third decimal place:
+当输入 `temperature` 的值无效时,函数返回空字符串,反之,则返回保留三位小数并四舍五入后的转换结果:
```js
function tryConvert(temperature, convert) {
@@ -146,11 +146,11 @@ function tryConvert(temperature, convert) {
}
```
-For example, `tryConvert('abc', toCelsius)` returns an empty string, and `tryConvert('10.22', toFahrenheit)` returns `'50.396'`.
+例如,`tryConvert('abc', toCelsius)` 返回一个空字符串,而 `tryConvert('10.22', toFahrenheit)` 返回 `'50.396'`。
-## Lifting State Up {#lifting-state-up}
+## 状态提升 {#lifting-state-up}
-Currently, both `TemperatureInput` components independently keep their values in the local state:
+到目前为止, 两个 `TemperatureInput` 组件均在各自内部的 state 中相互独立地保存着各自的数据。
```js{5,9,13}
class TemperatureInput extends React.Component {
@@ -169,15 +169,15 @@ class TemperatureInput extends React.Component {
// ...
```
-However, we want these two inputs to be in sync with each other. When we update the Celsius input, the Fahrenheit input should reflect the converted temperature, and vice versa.
+然而,我们希望两个输入框内的数值彼此能够同步。当我们更新摄氏度输入框内的数值时,华氏度输入框内应当显示转换后的华氏温度,反之亦然。
-In React, sharing state is accomplished by moving it up to the closest common ancestor of the components that need it. This is called "lifting state up". We will remove the local state from the `TemperatureInput` and move it into the `Calculator` instead.
+在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”。接下来,我们将 `TemperatureInput` 组件中的 state 移动至 `Calculator` 组件中去。
-If the `Calculator` owns the shared state, it becomes the "source of truth" for the current temperature in both inputs. It can instruct them both to have values that are consistent with each other. Since the props of both `TemperatureInput` components are coming from the same parent `Calculator` component, the two inputs will always be in sync.
+如果 `Calculator` 组件拥有了共享的 state,它将成为两个温度输入框中当前温度的“数据源”。它能够使得两个温度输入框的数值彼此保持一致。由于两个 `TemperatureInput` 组件的 props 均来自共同的父组件 `Calculator`,因此两个输入框中的内容将始终保持一致。
-Let's see how this works step by step.
+让我们看看这是如何一步一步实现的。
-First, we will replace `this.state.temperature` with `this.props.temperature` in the `TemperatureInput` component. For now, let's pretend `this.props.temperature` already exists, although we will need to pass it from the `Calculator` in the future:
+首先,我们将 `TemperatureInput` 组件中的 `this.state.temperature` 替换为 `this.props.temperature`。现在,我们先假定 `this.props.temperature` 已经存在,尽管将来我们需要通过 `Calculator` 组件将其传入:
```js{3}
render() {
@@ -186,11 +186,11 @@ First, we will replace `this.state.temperature` with `this.props.temperature` in
// ...
```
-We know that [props are read-only](/docs/components-and-props.html#props-are-read-only). When the `temperature` was in the local state, the `TemperatureInput` could just call `this.setState()` to change it. However, now that the `temperature` is coming from the parent as a prop, the `TemperatureInput` has no control over it.
+我们知道 [props 是只读的](/docs/components-and-props.html#props-are-read-only)。当 `temperature` 存在于 `TemperatureInput` 组件的 state 中时,组件调用 `this.setState()` 便可修改它。然而,`temperature` 是由父组件传入的 prop,`TemperatureInput` 组件便失去了对它的控制权。
-In React, this is usually solved by making a component "controlled". Just like the DOM `` accepts both a `value` and an `onChange` prop, so can the custom `TemperatureInput` accept both `temperature` and `onTemperatureChange` props from its parent `Calculator`.
+在 React 中,这个问题通常是通过使用“受控组件”来解决的。与 DOM 中的 `` 接受 `value` 和 `onChange` 一样,自定义的 `TemperatureInput` 组件接受 `temperature` 和 `onTemperatureChange` 这两个来自父组件 `Calculator` 的 props。
-Now, when the `TemperatureInput` wants to update its temperature, it calls `this.props.onTemperatureChange`:
+现在,当 `TemperatureInput` 组件想更新温度时,需调用 `this.props.onTemperatureChange` 来更新它:
```js{3}
handleChange(e) {
@@ -199,13 +199,13 @@ Now, when the `TemperatureInput` wants to update its temperature, it calls `this
// ...
```
->Note:
+>注意:
>
->There is no special meaning to either `temperature` or `onTemperatureChange` prop names in custom components. We could have called them anything else, like name them `value` and `onChange` which is a common convention.
+>自定义组件中的 `temperature` 和 `onTemperatureChange` 这两个 prop 的命名没有任何特殊含义。我们可以给它们取其它任意的名字,例如,把它们命名为 `value` 和 `onChange` 就是一种习惯。
-The `onTemperatureChange` prop will be provided together with the `temperature` prop by the parent `Calculator` component. It will handle the change by modifying its own local state, thus re-rendering both inputs with the new values. We will look at the new `Calculator` implementation very soon.
+`onTemperatureChange` 的 prop 和 `temperature` 的 prop 一样,均由父组件 `Calculator` 提供。它通过修改父组件自身的内部 state 来处理数据的变化,进而使用新的数值重新渲染两个输入框。我们将很快看到修改后的 `Calculator` 组件效果。
-Before diving into the changes in the `Calculator`, let's recap our changes to the `TemperatureInput` component. We have removed the local state from it, and instead of reading `this.state.temperature`, we now read `this.props.temperature`. Instead of calling `this.setState()` when we want to make a change, we now call `this.props.onTemperatureChange()`, which will be provided by the `Calculator`:
+在深入研究 `Calculator` 组件的变化之前,让我们回顾一下 `TemperatureInput` 组件的变化。我们移除组件自身的 state,通过使用 `this.props.temperature` 替代 `this.state.temperature` 来读取温度数据。当我们想要响应数据改变时,我们需要调用 `Calculator` 组件提供的 `this.props.onTemperatureChange()`,而不再使用 `this.setState()`。
```js{8,12}
class TemperatureInput extends React.Component {
@@ -232,11 +232,11 @@ class TemperatureInput extends React.Component {
}
```
-Now let's turn to the `Calculator` component.
+现在,让我们把目光转向 `Calculator` 组件。
-We will store the current input's `temperature` and `scale` in its local state. This is the state we "lifted up" from the inputs, and it will serve as the "source of truth" for both of them. It is the minimal representation of all the data we need to know in order to render both inputs.
+我们会把当前输入的 `temperature` 和 `scale` 保存在组件内部的 state 中。这个 state 就是从两个输入框组件中“提升”而来的,并且它将用作两个输入框组件的共同“数据源”。这是我们为了渲染两个输入框所需要的所有数据的最小表示。
-For example, if we enter 37 into the Celsius input, the state of the `Calculator` component will be:
+例如,当我们在摄氏度输入框中键入 37 时,`Calculator` 组件中的 state 将会是:
```js
{
@@ -245,7 +245,7 @@ For example, if we enter 37 into the Celsius input, the state of the `Calculator
}
```
-If we later edit the Fahrenheit field to be 212, the state of the `Calculator` will be:
+如果我们之后修改华氏度的输入框中的内容为 212 时,`Calculator` 组件中的 state 将会是:
```js
{
@@ -254,9 +254,9 @@ If we later edit the Fahrenheit field to be 212, the state of the `Calculator` w
}
```
-We could have stored the value of both inputs but it turns out to be unnecessary. It is enough to store the value of the most recently changed input, and the scale that it represents. We can then infer the value of the other input based on the current `temperature` and `scale` alone.
+我们可以存储两个输入框中的值,但这并不是必要的。我们只需要存储最近修改的温度及其计量单位即可,根据当前的 `temperature` 和 `scale` 就可以计算出另一个输入框的值。
-The inputs stay in sync because their values are computed from the same state:
+由于两个输入框中的数值由同一个 state 计算而来,因此它们始终保持同步:
```js{6,10,14,18-21,27-28,31-32,34}
class Calculator extends React.Component {
@@ -299,32 +299,32 @@ class Calculator extends React.Component {
}
```
-[**Try it on CodePen**](https://codepen.io/gaearon/pen/WZpxpz?editors=0010)
+[**在 CodePen 上尝试**](https://codepen.io/gaearon/pen/WZpxpz?editors=0010)
-Now, no matter which input you edit, `this.state.temperature` and `this.state.scale` in the `Calculator` get updated. One of the inputs gets the value as is, so any user input is preserved, and the other input value is always recalculated based on it.
+现在无论你编辑哪个输入框中的内容,`Calculator` 组件中的 `this.state.temperature` 和 `this.state.scale` 均会被更新。其中一个输入框保留用户的输入并取值,另一个输入框始终基于这个值显示转换后的结果。
-Let's recap what happens when you edit an input:
+让我们来重新梳理一下当你对输入框内容进行编辑时会发生些什么:
-* React calls the function specified as `onChange` on the DOM ``. In our case, this is the `handleChange` method in the `TemperatureInput` component.
-* The `handleChange` method in the `TemperatureInput` component calls `this.props.onTemperatureChange()` with the new desired value. Its props, including `onTemperatureChange`, were provided by its parent component, the `Calculator`.
-* When it previously rendered, the `Calculator` has specified that `onTemperatureChange` of the Celsius `TemperatureInput` is the `Calculator`'s `handleCelsiusChange` method, and `onTemperatureChange` of the Fahrenheit `TemperatureInput` is the `Calculator`'s `handleFahrenheitChange` method. So either of these two `Calculator` methods gets called depending on which input we edited.
-* Inside these methods, the `Calculator` component asks React to re-render itself by calling `this.setState()` with the new input value and the current scale of the input we just edited.
-* React calls the `Calculator` component's `render` method to learn what the UI should look like. The values of both inputs are recomputed based on the current temperature and the active scale. The temperature conversion is performed here.
-* React calls the `render` methods of the individual `TemperatureInput` components with their new props specified by the `Calculator`. It learns what their UI should look like.
-* React calls the `render` method of the `BoilingVerdict` component, passing the temperature in Celsius as its props.
-* React DOM updates the DOM with the boiling verdict and to match the desired input values. The input we just edited receives its current value, and the other input is updated to the temperature after conversion.
+* React 会调用 DOM 中 `` 的 `onChange` 方法。在本实例中,它是 `TemperatureInput` 组件的 `handleChange` 方法。
+* `TemperatureInput` 组件中的 `handleChange` 方法会调用 `this.props.onTemperatureChange()`,并传入新输入的值作为参数。其 props 诸如 `onTemperatureChange` 之类,均由父组件 `Calculator` 提供。
+* 起初渲染时,用于摄氏度输入的子组件 `TemperatureInput` 中 `onTemperatureChange` 方法为 `Calculator` 组件中的 `handleCelsiusChange` 方法,而,用于华氏度输入的子组件 `TemperatureInput` 中的 `onTemperatureChange` 方法为 `Calculator` 组件中的 `handleFahrenheitChange` 方法。因此,无论哪个输入框被编辑都会调用 `Calculator` 组件中对应的方法。
+* 在这些方法内部,`Calculator` 组件通过使用新的输入值与当前输入框对应的温度计量单位来调用 `this.setState()` 进而请求 React 重新渲染自己本身。
+* React 调用 `Calculator` 组件的 `render` 方法得到组件的 UI 呈现。温度转换在这时进行,两个输入框中的数值通过当前输入温度和其计量单位来重新计算获得。
+* React 使用 `Calculator` 组件提供的新 props 分别调用两个 `TemperatureInput` 子组件的 `render` 方法来获取子组件的 UI 呈现。
+* React 调用 `BoilingVerdict` 组件的 `render` 方法,并将摄氏温度值以组件 props 方式传入。
+* React DOM 根据输入值匹配水是否沸腾,并将结果更新至 DOM。我们刚刚编辑的输入框接收其当前值,另一个输入框内容更新为转换后的温度值。
-Every update goes through the same steps so the inputs stay in sync.
+得益于每次的更新都经历相同的步骤,两个输入框的内容才能始终保持同步。
-## Lessons Learned {#lessons-learned}
+## 学习小结 {#lessons-learned}
-There should be a single "source of truth" for any data that changes in a React application. Usually, the state is first added to the component that needs it for rendering. Then, if other components also need it, you can lift it up to their closest common ancestor. Instead of trying to sync the state between different components, you should rely on the [top-down data flow](/docs/state-and-lifecycle.html#the-data-flows-down).
+在 React 应用中,任何可变数据应当只有一个相对应的唯一“数据源”。通常,state 都是首先添加到需要渲染数据的组件中去。然后,如果其他组件也需要这个 state,那么你可以将它提升至这些组件的最近共同父组件中。你应当依靠[自上而下的数据流](/docs/state-and-lifecycle.html#the-data-flows-down),而不是尝试在不同组件间同步 state。
-Lifting state involves writing more "boilerplate" code than two-way binding approaches, but as a benefit, it takes less work to find and isolate bugs. Since any state "lives" in some component and that component alone can change it, the surface area for bugs is greatly reduced. Additionally, you can implement any custom logic to reject or transform user input.
+虽然提升 state 方式比双向绑定方式需要编写更多的“样板”代码,但带来的好处是,排查和隔离 bug 所需的工作量将会变少。由于“存在”于组件中的任何 state,仅有组件自己能够修改它,因此 bug 的排查范围被大大缩减了。此外,你也可以使用自定义逻辑来拒绝或转换用户的输入。
-If something can be derived from either props or state, it probably shouldn't be in the state. For example, instead of storing both `celsiusValue` and `fahrenheitValue`, we store just the last edited `temperature` and its `scale`. The value of the other input can always be calculated from them in the `render()` method. This lets us clear or apply rounding to the other field without losing any precision in the user input.
+如果某些数据可以由 props 或 state 推导得出,那么它就不应该存在于 state 中。举个例子,本例中我们没有将 `celsiusValue` 和 `fahrenheitValue` 一起保存,而是仅保存了最后修改的 `temperature` 和它的 `scale`。这是因为另一个输入框的温度值始终可以通过这两个值以及组件的 `render()` 方法获得。这使得我们能够清除输入框内容,亦或是,在不损失用户操作的输入框内数值精度的前提下对另一个输入框内的转换数值做四舍五入的操作。
-When you see something wrong in the UI, you can use [React Developer Tools](https://github.com/facebook/react-devtools) to inspect the props and move up the tree until you find the component responsible for updating the state. This lets you trace the bugs to their source:
+当你在 UI 中发现错误时,可以使用 [React 开发者工具](https://github.com/facebook/react-devtools) 来检查问题组件的 props,并且按照组件树结构逐级向上搜寻,直到定位到负责更新 state 的那个组件。这使得你能够追踪到产生 bug 的源头: