diff --git a/src/content/learn/updating-objects-in-state.md b/src/content/learn/updating-objects-in-state.md
index 9289f2454a..cb6c84f555 100644
--- a/src/content/learn/updating-objects-in-state.md
+++ b/src/content/learn/updating-objects-in-state.md
@@ -1,57 +1,61 @@
 ---
-title: Updating Objects in State
+title: 更新 state 中的对象 
+translators:
+  - Neo42
+  - yliaz
+  - Debbl
 ---
 
 <Intro>
 
-State can hold any kind of JavaScript value, including objects. But you shouldn't change objects that you hold in the React state directly. Instead, when you want to update an object, you need to create a new one (or make a copy of an existing one), and then set the state to use that copy.
+state 中可以保存任意类型的 JavaScript 值,包括对象。但是,你不应该直接修改存放在 React state 中的对象。相反,当你想要更新一个对象时,你需要创建一个新的对象(或者将其拷贝一份),然后将 state 更新为此对象。
 
 </Intro>
 
 <YouWillLearn>
 
-- How to correctly update an object in React state
-- How to update a nested object without mutating it
-- What immutability is, and how not to break it
-- How to make object copying less repetitive with Immer
+- 如何正确地更新 React state 中的对象
+- 如何在不产生 mutation 的情况下更新一个嵌套对象
+- 什么是不可变性(immutability),以及如何不破坏它
+- 如何使用 Immer 使复制对象不那么繁琐 
 
 </YouWillLearn>
 
-## What's a mutation? {/*whats-a-mutation*/}
+## 什么是 mutation? {/*whats-a-mutation*/}
 
-You can store any kind of JavaScript value in state.
+你可以在 state 中存放任意类型的 JavaScript 值。
 
 ```js
 const [x, setX] = useState(0);
 ```
 
-So far you've been working with numbers, strings, and booleans. These kinds of JavaScript values are "immutable", meaning unchangeable or "read-only". You can trigger a re-render to _replace_ a value:
+到目前为止,你已经尝试过在 state 中存放数字、字符串和布尔值,这些类型的值在 JavaScript 中是不可变(immutable)的,这意味着它们不能被改变或是只读的。你可以通过替换它们的值以触发一次重新渲染。
 
 ```js
 setX(5);
 ```
 
-The `x` state changed from `0` to `5`, but the _number `0` itself_ did not change. It's not possible to make any changes to the built-in primitive values like numbers, strings, and booleans in JavaScript.
+state `x` 从 `0` 变为 `5`,但是数字 `0` 本身并没有发生改变。在 JavaScript 中,无法对内置的原始值,如数字、字符串和布尔值,进行任何更改。
 
-Now consider an object in state:
+现在考虑 state 中存放对象的情况:
 
 ```js
 const [position, setPosition] = useState({ x: 0, y: 0 });
 ```
 
-Technically, it is possible to change the contents of _the object itself_. **This is called a mutation:**
+从技术上来讲,可以改变对象自身的内容。**当你这样做时,就制造了一个 mutation**:
 
 ```js
 position.x = 5;
 ```
 
-However, although objects in React state are technically mutable, you should treat them **as if** they were immutable--like numbers, booleans, and strings. Instead of mutating them, you should always replace them.
+然而,虽然严格来说 React state 中存放的对象是可变的,但你应该像处理数字、布尔值、字符串一样将它们视为不可变的。因此你应该替换它们的值,而不是对它们进行修改。
 
-## Treat state as read-only {/*treat-state-as-read-only*/}
+## 将 state 视为只读的 {/*treat-state-as-read-only*/}
 
-In other words, you should **treat any JavaScript object that you put into state as read-only.**
+换句话说,你应该 **把所有存放在 state 中的 JavaScript 对象都视为只读的**。
 
-This example holds an object in state to represent the current pointer position. The red dot is supposed to move when you touch or move the cursor over the preview area. But the dot stays in the initial position:
+在下面的例子中,我们用一个存放在 state 中的对象来表示指针当前的位置。当你在预览区触摸或移动光标时,红色的点本应移动。但是实际上红点仍停留在原处:
 
 <Sandpack>
 
@@ -94,7 +98,7 @@ body { margin: 0; padding: 0; height: 250px; }
 
 </Sandpack>
 
-The problem is with this bit of code.
+问题出在下面这段代码中。
 
 ```js
 onPointerMove={e => {
@@ -103,9 +107,9 @@ onPointerMove={e => {
 }}
 ```
 
-This code modifies the object assigned to `position` from [the previous render.](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) But without using the state setting function, React has no idea that object has changed. So React does not do anything in response. It's like trying to change the order after you've already eaten the meal. While mutating state can work in some cases, we don't recommend it. You should treat the state value you have access to in a render as read-only.
+这段代码直接修改了 [上一次渲染中](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) 分配给 `position` 的对象。但是因为并没有使用 state 的设置函数,React 并不知道对象已更改。所以 React 没有做出任何响应。这就像在吃完饭之后才尝试去改变要点的菜一样。虽然在一些情况下,直接修改 state 可能是有效的,但我们并不推荐这么做。你应该把在渲染过程中可以访问到的 state 视为只读的。
 
-To actually [trigger a re-render](/learn/state-as-a-snapshot#setting-state-triggers-renders) in this case, **create a *new* object and pass it to the state setting function:**
+在这种情况下,为了真正地 [触发一次重新渲染](/learn/state-as-a-snapshot#setting-state-triggers-renders),**你需要创建一个新对象并把它传递给 state 的设置函数**:
 
 ```js
 onPointerMove={e => {
@@ -116,12 +120,12 @@ onPointerMove={e => {
 }}
 ```
 
-With `setPosition`, you're telling React:
+通过使用 `setPosition`,你在告诉 React:
 
-* Replace `position` with this new object
-* And render this component again
+* 使用这个新的对象替换 `position` 的值
+* 然后再次渲染这个组件
 
-Notice how the red dot now follows your pointer when you touch or hover over the preview area:
+现在你可以看到,当你在预览区触摸或移动光标时,红点会跟随着你的指针移动:
 
 <Sandpack>
 
@@ -168,16 +172,16 @@ body { margin: 0; padding: 0; height: 250px; }
 
 <DeepDive>
 
-#### Local mutation is fine {/*local-mutation-is-fine*/}
+#### 局部 mutation 是可以接受的 {/*local-mutation-is-fine*/}
 
-Code like this is a problem because it modifies an *existing* object in state:
+像这样的代码是有问题的,因为它改变了 state 中现有的对象:
 
 ```js
 position.x = e.clientX;
 position.y = e.clientY;
 ```
 
-But code like this is **absolutely fine** because you're mutating a fresh object you have *just created*:
+但是像这样的代码就 **没有任何问题**,因为你改变的是你刚刚创建的一个新的对象:
 
 ```js
 const nextPosition = {};
@@ -186,7 +190,7 @@ nextPosition.y = e.clientY;
 setPosition(nextPosition);
 ```
 
-In fact, it is completely equivalent to writing this:
+事实上,它完全等同于下面这种写法:
 
 ```js
 setPosition({
@@ -195,15 +199,15 @@ setPosition({
 });
 ```
 
-Mutation is only a problem when you change *existing* objects that are already in state. Mutating an object you've just created is okay because *no other code references it yet.* Changing it isn't going to accidentally impact something that depends on it. This is called a "local mutation". You can even do local mutation [while rendering.](/learn/keeping-components-pure#local-mutation-your-components-little-secret) Very convenient and completely okay!
+只有当你改变已经处于 state 中的 **现有** 对象时,mutation 才会成为问题。而修改一个你刚刚创建的对象就不会出现任何问题,因为 **还没有其他的代码引用它**。改变它并不会意外地影响到依赖它的东西。这叫做“局部 mutation”。你甚至可以 [在渲染的过程中](/learn/keeping-components-pure#local-mutation-your-components-little-secret) 进行“局部 mutation”的操作。这种操作既便捷又没有任何问题!
 
 </DeepDive>  
 
-## Copying objects with the spread syntax {/*copying-objects-with-the-spread-syntax*/}
+## 使用展开语法复制对象 {/*copying-objects-with-the-spread-syntax*/}
 
-In the previous example, the `position` object is always created fresh from the current cursor position. But often, you will want to include *existing* data as a part of the new object you're creating. For example, you may want to update *only one* field in a form, but keep the previous values for all other fields.
+在之前的例子中,始终会根据当前指针的位置创建出一个新的 `position` 对象。但是通常,你会希望把 **现有** 数据作为你所创建的新对象的一部分。例如,你可能只想要更新表单中的一个字段,其他的字段仍然使用之前的值。
 
-These input fields don't work because the `onChange` handlers mutate the state:
+下面的代码中,输入框并不会正常运行,因为 `onChange` 直接修改了 state :
 
 <Sandpack>
 
@@ -269,34 +273,34 @@ input { margin-left: 5px; margin-bottom: 5px; }
 
 </Sandpack>
 
-For example, this line mutates the state from a past render:
+例如,下面这行代码修改了上一次渲染中的 state:
 
 ```js
 person.firstName = e.target.value;
 ```
 
-The reliable way to get the behavior you're looking for is to create a new object and pass it to `setPerson`. But here, you want to also **copy the existing data into it** because only one of the fields has changed:
+想要实现你的需求,最可靠的办法就是创建一个新的对象并将它传递给 `setPerson`。但是在这里,你还需要 **把当前的数据复制到新对象中**,因为你只改变了其中一个字段:
 
 ```js
 setPerson({
-  firstName: e.target.value, // New first name from the input
+  firstName: e.target.value, // 从 input 中获取新的 first name
   lastName: person.lastName,
   email: person.email
 });
 ```
 
-You can use the `...` [object spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_object_literals) syntax so that you don't need to copy every property separately.
+你可以使用 `...` [对象展开](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_object_literals) 语法,这样你就不需要单独复制每个属性。
 
 ```js
 setPerson({
-  ...person, // Copy the old fields
-  firstName: e.target.value // But override this one
+  ...person, // 复制上一个 person 中的所有字段
+  firstName: e.target.value // 但是覆盖 firstName 字段 
 });
 ```
 
-Now the form works! 
+现在表单可以正常运行了!
 
-Notice how you didn't declare a separate state variable for each input field. For large forms, keeping all data grouped in an object is very convenient--as long as you update it correctly!
+可以看到,你并没有为每个输入框单独声明一个 state。对于大型表单,将所有数据都存放在同一个对象中是非常方便的——前提是你能够正确地更新它!
 
 <Sandpack>
 
@@ -371,13 +375,13 @@ input { margin-left: 5px; margin-bottom: 5px; }
 
 </Sandpack>
 
-Note that the `...` spread syntax is "shallow"--it only copies things one level deep. This makes it fast, but it also means that if you want to update a nested property, you'll have to use it more than once. 
+请注意 `...` 展开语法本质是是“浅拷贝”——它只会复制一层。这使得它的执行速度很快,但是也意味着当你想要更新一个嵌套属性时,你必须得多次使用展开语法。
 
 <DeepDive>
 
-#### Using a single event handler for multiple fields {/*using-a-single-event-handler-for-multiple-fields*/}
+#### 使用一个事件处理函数来更新多个字段 {/*using-a-single-event-handler-for-multiple-fields*/}
 
-You can also use the `[` and `]` braces inside your object definition to specify a property with dynamic name. Here is the same example, but with a single event handler instead of three different ones:
+你也可以在对象的定义中使用 `[` 和 `]` 括号来实现属性的动态命名。下面是同一个例子,但它使用了一个事件处理函数而不是三个:
 
 <Sandpack>
 
@@ -441,13 +445,13 @@ input { margin-left: 5px; margin-bottom: 5px; }
 
 </Sandpack>
 
-Here, `e.target.name` refers to the `name` property given to the `<input>` DOM element.
+在这里,`e.target.name` 引用了 `<input>` 这个 DOM 元素的 `name` 属性。
 
 </DeepDive>
 
-## Updating a nested object {/*updating-a-nested-object*/}
+## 更新一个嵌套对象 {/*updating-a-nested-object*/}
 
-Consider a nested object structure like this:
+考虑下面这种结构的嵌套对象:
 
 ```js
 const [person, setPerson] = useState({
@@ -460,13 +464,13 @@ const [person, setPerson] = useState({
 });
 ```
 
-If you wanted to update `person.artwork.city`, it's clear how to do it with mutation:
+如果你想要更新 `person.artwork.city` 的值,用 mutation 来实现的方法非常容易理解:
 
 ```js
 person.artwork.city = 'New Delhi';
 ```
 
-But in React, you treat state as immutable! In order to change `city`, you would first need to produce the new `artwork` object (pre-populated with data from the previous one), and then produce the new `person` object which points at the new `artwork`:
+但是在 React 中,你需要将 state 视为不可变的!为了修改 `city` 的值,你首先需要创建一个新的 `artwork` 对象(其中预先填充了上一个 `artwork` 对象中的数据),然后创建一个新的 `person` 对象,并使得其中的 `artwork` 属性指向新创建的 `artwork` 对象:
 
 ```js
 const nextArtwork = { ...person.artwork, city: 'New Delhi' };
@@ -474,19 +478,19 @@ const nextPerson = { ...person, artwork: nextArtwork };
 setPerson(nextPerson);
 ```
 
-Or, written as a single function call:
+或者,写成一个函数调用:
 
 ```js
 setPerson({
-  ...person, // Copy other fields
-  artwork: { // but replace the artwork
-    ...person.artwork, // with the same one
-    city: 'New Delhi' // but in New Delhi!
+  ...person, // 复制其它字段的数据 
+  artwork: { // 替换 artwork 字段 
+    ...person.artwork, // 复制之前 person.artwork 中的数据
+    city: 'New Delhi' // 但是将 city 的值替换为 New Delhi!
   }
 });
 ```
 
-This gets a bit wordy, but it works fine for many cases:
+这虽然看起来有点冗长,但对于很多情况都能有效地解决问题:
 
 <Sandpack>
 
@@ -596,9 +600,9 @@ img { width: 200px; height: 200px; }
 
 <DeepDive>
 
-#### Objects are not really nested {/*objects-are-not-really-nested*/}
+#### 对象并非是真正嵌套的 {/*objects-are-not-really-nested*/}
 
-An object like this appears "nested" in code:
+下面这个对象从代码上来看是“嵌套”的:
 
 ```js
 let obj = {
@@ -611,7 +615,7 @@ let obj = {
 };
 ```
 
-However, "nesting" is an inaccurate way to think about how objects behave. When the code executes, there is no such thing as a "nested" object. You are really looking at two different objects:
+然而,当我们思考对象的特性时,“嵌套”并不是一个非常准确的方式。当这段代码运行的时候,不存在“嵌套”的对象。你实际上看到的是两个不同的对象:
 
 ```js
 let obj1 = {
@@ -626,7 +630,7 @@ let obj2 = {
 };
 ```
 
-The `obj1` object is not "inside" `obj2`. For example, `obj3` could "point" at `obj1` too:
+对象 `obj1` 并不处于 `obj2` 的“内部”。例如,下面的代码中,`obj3` 中的属性也可以指向 `obj1`:
 
 ```js
 let obj1 = {
@@ -646,13 +650,13 @@ let obj3 = {
 };
 ```
 
-If you were to mutate `obj3.artwork.city`, it would affect both `obj2.artwork.city` and `obj1.city`. This is because `obj3.artwork`, `obj2.artwork`, and `obj1` are the same object. This is difficult to see when you think of objects as "nested". Instead, they are separate objects "pointing" at each other with properties.
+如果你直接修改 `obj3.artwork.city`,就会同时影响 `obj2.artwork.city` 和 `obj1.city`。这是因为 `obj3.artwork`、`obj2.artwork` 和 `obj1` 都指向同一个对象。当你用“嵌套”的方式看待对象时,很难看出这一点。相反,它们是相互独立的对象,只不过是用属性“指向”彼此而已。
 
 </DeepDive>  
 
-### Write concise update logic with Immer {/*write-concise-update-logic-with-immer*/}
+### 使用 Immer 编写简洁的更新逻辑 {/*write-concise-update-logic-with-immer*/}
 
-If your state is deeply nested, you might want to consider [flattening it.](/learn/choosing-the-state-structure#avoid-deeply-nested-state) But, if you don't want to change your state structure, you might prefer a shortcut to nested spreads. [Immer](https://github.com/immerjs/use-immer) is a popular library that lets you write using the convenient but mutating syntax and takes care of producing the copies for you. With Immer, the code you write looks like you are "breaking the rules" and mutating an object:
+如果你的 state 有多层的嵌套,你或许应该考虑 [将其扁平化](/learn/choosing-the-state-structure#avoid-deeply-nested-state)。但是,如果你不想改变 state 的数据结构,你可能更喜欢用一种更便捷的方式来实现嵌套展开的效果。[Immer](https://github.com/immerjs/use-immer) 是一个非常流行的库,它可以让你使用简便但可以直接修改的语法编写代码,并会帮你处理好复制的过程。通过使用 Immer,你写出的代码看起来就像是你“打破了规则”而直接修改了对象:
 
 ```js
 updatePerson(draft => {
@@ -660,22 +664,22 @@ updatePerson(draft => {
 });
 ```
 
-But unlike a regular mutation, it doesn't overwrite the past state!
+但是不同于一般的 mutation,它并不会覆盖之前的 state!
 
 <DeepDive>
 
-#### How does Immer work? {/*how-does-immer-work*/}
+#### Immer 是如何运行的? {/*how-does-immer-work*/}
 
-The `draft` provided by Immer is a special type of object, called a [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy), that "records" what you do with it. This is why you can mutate it freely as much as you like! Under the hood, Immer figures out which parts of the `draft` have been changed, and produces a completely new object that contains your edits.
+由 Immer 提供的 `draft` 是一种特殊类型的对象,被称为 [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy),它会记录你用它所进行的操作。这就是你能够随心所欲地直接修改对象的原因所在!从原理上说,Immer 会弄清楚 `draft` 对象的哪些部分被改变了,并会依照你的修改创建出一个全新的对象。
 
 </DeepDive>
 
-To try Immer:
+尝试使用 Immer:
 
-1. Run `npm install use-immer` to add Immer as a dependency
-2. Then replace `import { useState } from 'react'` with `import { useImmer } from 'use-immer'`
+1. 运行 `npm install use-immer` 添加 Immer 依赖
+2. 用 `import { useImmer } from 'use-immer'` 替换掉 `import { useState } from 'react'`
 
-Here is the above example converted to Immer:
+下面我们把上面的例子用 Immer 实现一下:
 
 <Sandpack>
 
@@ -788,33 +792,33 @@ img { width: 200px; height: 200px; }
 
 </Sandpack>
 
-Notice how much more concise the event handlers have become. You can mix and match `useState` and `useImmer` in a single component as much as you like. Immer is a great way to keep the update handlers concise, especially if there's nesting in your state, and copying objects leads to repetitive code.
+可以看到,事件处理函数变得更简洁了。你可以随意在一个组件中同时使用 `useState` 和 `useImmer`。如果你想要写出更简洁的更新处理函数,Immer 会是一个不错的选择,尤其是当你的 state 中有嵌套,并且复制对象会带来重复的代码时。
 
 <DeepDive>
 
-#### Why is mutating state not recommended in React? {/*why-is-mutating-state-not-recommended-in-react*/}
+#### 为什么在 React 中不推荐直接修改 state? {/*why-is-mutating-state-not-recommended-in-react*/}
 
-There are a few reasons:
+有以下几个原因:
 
-* **Debugging:** If you use `console.log` and don't mutate state, your past logs won't get clobbered by the more recent state changes. So you can clearly see how state has changed between renders.
-* **Optimizations:** Common React [optimization strategies](/reference/react/memo) rely on skipping work if previous props or state are the same as the next ones. If you never mutate state, it is very fast to check whether there were any changes. If `prevObj === obj`, you can be sure that nothing could have changed inside of it.
-* **New Features:** The new React features we're building rely on state being [treated like a snapshot.](/learn/state-as-a-snapshot) If you're mutating past versions of state, that may prevent you from using the new features.
-* **Requirement Changes:** Some application features, like implementing Undo/Redo, showing a history of changes, or letting the user reset a form to earlier values, are easier to do when nothing is mutated. This is because you can keep past copies of state in memory, and reuse them when appropriate. If you start with a mutative approach, features like this can be difficult to add later on.
-* **Simpler Implementation:** Because React does not rely on mutation, it does not need to do anything special with your objects. It does not need to hijack their properties, always wrap them into Proxies, or do other work at initialization as many "reactive" solutions do. This is also why React lets you put any object into state--no matter how large--without additional performance or correctness pitfalls.
+* **调试**:如果你使用 `console.log` 并且不直接修改 state,你之前日志中的 state 的值就不会被新的 state 变化所影响。这样你就可以清楚地看到两次渲染之间 state 的值发生了什么变化
+* **优化**:React 常见的 [优化策略](/reference/react/memo) 依赖于如果之前的 props 或者 state 的值和下一次相同就跳过渲染。如果你从未直接修改 state ,那么你就可以很快看到 state 是否发生了变化。如果 `prevObj === obj`,那么你就可以肯定这个对象内部并没有发生改变。
+* **新功能**:我们正在构建的 React 的新功能依赖于 state 被 [像快照一样看待](/learn/state-as-a-snapshot) 的理念。如果你直接修改 state 的历史版本,可能会影响你使用这些新功能。
+* **需求变更**:有些应用功能在不出现任何修改的情况下会更容易实现,比如实现撤销/恢复、展示修改历史,或是允许用户把表单重置成某个之前的值。这是因为你可以把 state 之前的拷贝保存到内存中,并适时对其进行再次使用。如果一开始就用了直接修改 state 的方式,那么后面要实现这样的功能就会变得非常困难。
+* **更简单的实现**:React 并不依赖于 mutation ,所以你不需要对对象进行任何特殊操作。它不需要像很多“响应式”的解决方案一样去劫持对象的属性、总是用代理把对象包裹起来,或者在初始化时做其他工作。这也是为什么 React 允许你把任何对象存放在 state 中——不管对象有多大——而不会造成有任何额外的性能或正确性问题的原因。
 
-In practice, you can often "get away" with mutating state in React, but we strongly advise you not to do that so that you can use new React features developed with this approach in mind. Future contributors and perhaps even your future self will thank you!
+在实践中,你经常可以“侥幸”直接修改 state 而不出现什么问题,但是我们强烈建议你不要这样做,这样你就可以使用我们秉承着这种理念开发的 React 新功能。未来的贡献者甚至是你未来的自己都会感谢你的!
 
 </DeepDive>
 
 <Recap>
 
-* Treat all state in React as immutable.
-* When you store objects in state, mutating them will not trigger renders and will change the state in previous render "snapshots".
-* Instead of mutating an object, create a *new* version of it, and trigger a re-render by setting state to it.
-* You can use the `{...obj, something: 'newValue'}` object spread syntax to create copies of objects.
-* Spread syntax is shallow: it only copies one level deep.
-* To update a nested object, you need to create copies all the way up from the place you're updating.
-* To reduce repetitive copying code, use Immer.
+* 将 React 中所有的 state 都视为不可直接修改的。
+* 当你在 state 中存放对象时,直接修改对象并不会触发重渲染,并会改变前一次渲染“快照”中 state 的值。
+* 不要直接修改一个对象,而要为它创建一个 **新** 版本,并通过把 state 设置成这个新版本来触发重新渲染。
+* 你可以使用这样的 `{...obj, something: 'newValue'}` 对象展开语法来创建对象的拷贝。
+* 对象的展开语法是浅层的:它的复制深度只有一层。
+* 想要更新嵌套对象,你需要从你更新的位置开始自底向上为每一层都创建新的拷贝。
+* 想要减少重复的拷贝代码,可以使用 Immer。
 
 </Recap>
 
@@ -822,11 +826,11 @@ In practice, you can often "get away" with mutating state in React, but we stron
 
 <Challenges>
 
-#### Fix incorrect state updates {/*fix-incorrect-state-updates*/}
+#### 修复错误的 state 更新代码 {/*fix-incorrect-state-updates*/}
 
-This form has a few bugs. Click the button that increases the score a few times. Notice that it does not increase. Then edit the first name, and notice that the score has suddenly "caught up" with your changes. Finally, edit the last name, and notice that the score has disappeared completely.
+这个表单有几个 bug。试着点击几次增加分数的按钮。你会注意到分数并没有增加。然后试着编辑一下名字字段,你会注意到分数突然“响应”了你之前的修改。最后,试着编辑一下姓氏字段,你会发现分数完全消失了。
 
-Your task is to fix all of these bugs. As you fix them, explain why each of them happens.
+你的任务就是修复所有的这些 bug。在你修复它们的同时,解释一下它们为什么会产生。
 
 <Sandpack>
 
@@ -894,7 +898,7 @@ input { margin-left: 5px; margin-bottom: 5px; }
 
 <Solution>
 
-Here is a version with both bugs fixed:
+下面是两个 bug 都得到修复后的代码:
 
 <Sandpack>
 
@@ -964,23 +968,23 @@ input { margin-left: 5px; margin-bottom: 5px; }
 
 </Sandpack>
 
-The problem with `handlePlusClick` was that it mutated the `player` object. As a result, React did not know that there's a reason to re-render, and did not update the score on the screen. This is why, when you edited the first name, the state got updated, triggering a re-render which _also_ updated the score on the screen.
+代码中 `handlePlusClick` 函数的问题在于它直接修改了 `player` 对象。这就造成了 React 并不知道需要重新渲染的原因,也就没有更新屏幕上分数的值。这就是为什么,当你修改名字字段的时候,state 发生了更新,state 更新触发了重新渲染,重新渲染**同时也**更新了屏幕上的分数。
 
-The problem with `handleLastNameChange` was that it did not copy the existing `...player` fields into the new object. This is why the score got lost after you edited the last name.
+代码中 `handleLastNameChange` 的问题在于它没有把 `...player` 中已有的属性复制到新的对象中。因此,当你编辑姓氏字段时,分数就丢失了。
 
 </Solution>
 
-#### Find and fix the mutation {/*find-and-fix-the-mutation*/}
+#### 发现并修复 mutation {/*find-and-fix-the-mutation*/}
 
-There is a draggable box on a static background. You can change the box's color using the select input.
+在静止的背景上有一个可以拖动的方形。你可以使用下拉框来修改方形的颜色。
 
-But there is a bug. If you move the box first, and then change its color, the background (which isn't supposed to move!) will "jump" to the box position. But this should not happen: the `Background`'s `position` prop is set to `initialPosition`, which is `{ x: 0, y: 0 }`. Why is the background moving after the color change?
+但是这里有个 bug。当你先移动了方形,再去修改它的颜色时,背景会突然“跳”到方形所在的位置(实际上背景的位置并不应该发生变化!)。但是这并不是我们想要的,`Background` 的 `position` 属性被设置为 `initialPosition`,也就是 `{ x: 0, y: 0 }`。为什么修改颜色之后,背景会移动呢?
 
-Find the bug and fix it.
+找到 bug 并修复它。
 
 <Hint>
 
-If something unexpected changes, there is a mutation. Find the mutation in `App.js` and fix it.
+如果有一些出乎意料的改变,就是 mutation,在 `App.js` 中找到 mutation 并修复它。
 
 </Hint>
 
@@ -1130,9 +1134,9 @@ select { margin-bottom: 10px; }
 
 <Solution>
 
-The problem was in the mutation inside `handleMove`. It mutated `shape.position`, but that's the same object that `initialPosition` points at. This is why both the shape and the background move. (It's a mutation, so the change doesn't reflect on the screen until an unrelated update--the color change--triggers a re-render.)
+问题出在 `handleMove` 中的 mutation 。它直接修改了 `shape.position`,但是此时 `initialPosition` 所指向的也是同一个对象。因此方形和背景都发生了移动。(因为它是 mutation,所以直到一个不相关更新——颜色变化——触发了一次重新渲染,变化才反映到屏幕上。)
 
-The fix is to remove the mutation from `handleMove`, and use the spread syntax to copy the shape. Note that `+=` is a mutation, so you need to rewrite it to use a regular `+` operation.
+修复问题的方法就是从 `handleMove` 中移除这个 mutation,然后用展开运算符来复制方形对象。请注意 `+=` 是 mutation 的一种,所以你需要对它进行重写来使用普通的 `+` 操作符。
 
 <Sandpack>
 
@@ -1285,9 +1289,9 @@ select { margin-bottom: 10px; }
 
 </Solution>
 
-#### Update an object with Immer {/*update-an-object-with-immer*/}
+#### 使用 Immer 更新对象 {/*update-an-object-with-immer*/}
 
-This is the same buggy example as in the previous challenge. This time, fix the mutation by using Immer. For your convenience, `useImmer` is already imported, so you need to change the `shape` state variable to use it.
+这里的例子和上面那段有 bug 的代码是相同的。这一次,试着用 Immer 来修复 mutation 的问题。为了方便你的练习,`useImmer` 已经被引入了,因此你只需要修改 `shape` 这个 state 变量来使用它。
 
 <Sandpack>
 
@@ -1454,7 +1458,7 @@ select { margin-bottom: 10px; }
 
 <Solution>
 
-This is the solution rewritten with Immer. Notice how the event handlers are written in a mutating fashion, but the bug does not occur. This is because under the hood, Immer never mutates the existing objects.
+下面的代码是使用 Immer 重写的。请注意代码中的事件处理函数仍然是以直接修改对象的方式书写的,但是代码不会产生任何问题了。这是因为从原理上来说,Immer 从来没有直接修改现有的对象。
 
 <Sandpack>