` làm con đầu tiên. Đối với React, hai counter này có cùng "địa chỉ": con đầu tiên của con đầu tiên của root. Đây là cách React khớp chúng giữa các lần render trước và sau, bất kể bạn cấu trúc logic như thế nào.
-## Different components at the same position reset state {/*different-components-at-the-same-position-reset-state*/}
+## Các component khác nhau ở cùng vị trí đặt lại state {/*different-components-at-the-same-position-reset-state*/}
-In this example, ticking the checkbox will replace `
` with a ``:
+Trong ví dụ này, việc tick vào checkbox sẽ thay thế `` bằng một ``:
@@ -561,13 +561,13 @@ label {
-Here, you switch between _different_ component types at the same position. Initially, the first child of the `
` contained a `Counter`. But when you swapped in a `p`, React removed the `Counter` from the UI tree and destroyed its state.
+Ở đây, bạn chuyển đổi giữa các loại component _khác nhau_ ở cùng vị trí. Ban đầu, con đầu tiên của `
` chứa một `Counter`. Nhưng khi bạn thay thế bằng một `p`, React đã xóa `Counter` khỏi cây UI và phá hủy state của nó.
-When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added
+Khi `Counter` thay đổi thành `p`, `Counter` bị xóa và `p` được thêm vào
@@ -577,13 +577,13 @@ When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added
-When switching back, the `p` is deleted and the `Counter` is added
+Khi chuyển đổi trở lại, `p` bị xóa và `Counter` được thêm vào
-Also, **when you render a different component in the same position, it resets the state of its entire subtree.** To see how this works, increment the counter and then tick the checkbox:
+Ngoài ra, **khi bạn render một component khác ở cùng vị trí, nó đặt lại state của toàn bộ cây con.** Để thấy cách hoạt động, hãy tăng counter rồi tick vào checkbox:
@@ -672,13 +672,13 @@ label {
-The counter state gets reset when you click the checkbox. Although you render a `Counter`, the first child of the `div` changes from a `section` to a `div`. When the child `section` was removed from the DOM, the whole tree below it (including the `Counter` and its state) was destroyed as well.
+State counter bị đặt lại khi bạn click vào checkbox. Mặc dù bạn render một `Counter`, con đầu tiên của `div` thay đổi từ `section` thành `div`. Khi `section` con bị xóa khỏi DOM, toàn bộ cây bên dưới nó (bao gồm `Counter` và state của nó) cũng bị phá hủy.
-When `section` changes to `div`, the `section` is deleted and the new `div` is added
+Khi `section` thay đổi thành `div`, `section` bị xóa và `div` mới được thêm vào
@@ -688,19 +688,19 @@ When `section` changes to `div`, the `section` is deleted and the new `div` is a
-When switching back, the `div` is deleted and the new `section` is added
+Khi chuyển đổi trở lại, `div` bị xóa và `section` mới được thêm vào
-As a rule of thumb, **if you want to preserve the state between re-renders, the structure of your tree needs to "match up"** from one render to another. If the structure is different, the state gets destroyed because React destroys state when it removes a component from the tree.
+Theo nguyên tắc chung, **nếu bạn muốn bảo tồn state giữa các lần render, cấu trúc cây của bạn cần "khớp"** từ lần render này sang lần render khác. Nếu cấu trúc khác nhau, state sẽ bị hủy vì React hủy state khi nó xóa một component khỏi cây.
-This is why you should not nest component function definitions.
+Đây là lý do tại sao bạn không nên lồng các định nghĩa function component.
-Here, the `MyTextField` component function is defined *inside* `MyComponent`:
+Ở đây, function component `MyTextField` được định nghĩa *bên trong* `MyComponent`:
@@ -735,13 +735,13 @@ export default function MyComponent() {
-Every time you click the button, the input state disappears! This is because a *different* `MyTextField` function is created for every render of `MyComponent`. You're rendering a *different* component in the same position, so React resets all state below. This leads to bugs and performance problems. To avoid this problem, **always declare component functions at the top level, and don't nest their definitions.**
+Mỗi lần bạn click vào button, state input sẽ biến mất! Điều này xảy ra vì một function `MyTextField` *khác* được tạo cho mỗi lần render của `MyComponent`. Bạn đang render một component *khác* ở cùng vị trí, vì vậy React đặt lại tất cả state bên dưới. Điều này dẫn đến bugs và vấn đề hiệu suất. Để tránh vấn đề này, **luôn khai báo các function component ở cấp độ cao nhất, và đừng lồng các định nghĩa của chúng.**
-## Resetting state at the same position {/*resetting-state-at-the-same-position*/}
+## Đặt lại state ở cùng vị trí {/*resetting-state-at-the-same-position*/}
-By default, React preserves state of a component while it stays at the same position. Usually, this is exactly what you want, so it makes sense as the default behavior. But sometimes, you may want to reset a component's state. Consider this app that lets two players keep track of their scores during each turn:
+Theo mặc định, React bảo tồn state của một component khi nó ở cùng vị trí. Thường thì, đây chính xác là điều bạn muốn, vì vậy nó hợp lý như hành vi mặc định. Nhưng đôi khi, bạn có thể muốn đặt lại state của một component. Hãy xem xét ứng dụng này cho phép hai người chơi theo dõi điểm số của họ trong mỗi lượt:
@@ -811,19 +811,19 @@ h1 {
-Currently, when you change the player, the score is preserved. The two `Counter`s appear in the same position, so React sees them as *the same* `Counter` whose `person` prop has changed.
+Hiện tại, khi bạn thay đổi người chơi, điểm số được bảo tồn. Hai `Counter` xuất hiện ở cùng vị trí, vì vậy React coi chúng là *cùng một* `Counter` có prop `person` đã thay đổi.
-But conceptually, in this app they should be two separate counters. They might appear in the same place in the UI, but one is a counter for Taylor, and another is a counter for Sarah.
+Nhưng về mặt khái niệm, trong ứng dụng này chúng nên là hai counter riêng biệt. Chúng có thể xuất hiện ở cùng vị trí trong UI, nhưng một cái là counter cho Taylor, và cái khác là counter cho Sarah.
-There are two ways to reset state when switching between them:
+Có hai cách để đặt lại state khi chuyển đổi giữa chúng:
-1. Render components in different positions
-2. Give each component an explicit identity with `key`
+1. Render các component ở các vị trí khác nhau
+2. Trao cho mỗi component một danh tính rõ ràng với `key`
-### Option 1: Rendering a component in different positions {/*option-1-rendering-a-component-in-different-positions*/}
+### Lựa chọn 1: Render một component ở các vị trí khác nhau {/*option-1-rendering-a-component-in-different-positions*/}
-If you want these two `Counter`s to be independent, you can render them in two different positions:
+Nếu bạn muốn hai `Counter` này độc lập, bạn có thể render chúng ở hai vị trí khác nhau:
@@ -894,42 +894,42 @@ h1 {
-* Initially, `isPlayerA` is `true`. So the first position contains `Counter` state, and the second one is empty.
-* When you click the "Next player" button the first position clears but the second one now contains a `Counter`.
+* Ban đầu, `isPlayerA` là `true`. Vậy vị trí đầu tiên chứa state `Counter`, và vị trí thứ hai trống.
+* Khi bạn click button "Next player", vị trí đầu tiên được xóa nhưng vị trí thứ hai giờ chứa một `Counter`.
-Initial state
+State ban đầu
-Clicking "next"
+Click "next"
-Clicking "next" again
+Click "next" lại
-Each `Counter`'s state gets destroyed each time it's removed from the DOM. This is why they reset every time you click the button.
+State của mỗi `Counter` bị hủy mỗi khi nó bị xóa khỏi DOM. Đây là lý do tại sao chúng đặt lại mỗi lần bạn click button.
-This solution is convenient when you only have a few independent components rendered in the same place. In this example, you only have two, so it's not a hassle to render both separately in the JSX.
+Giải pháp này thuận tiện khi bạn chỉ có một vài component độc lập được render ở cùng chỗ. Trong ví dụ này, bạn chỉ có hai, vì vậy việc render cả hai riêng biệt trong JSX không phiền hà.
-### Option 2: Resetting state with a key {/*option-2-resetting-state-with-a-key*/}
+### Lựa chọn 2: Đặt lại state với một key {/*option-2-resetting-state-with-a-key*/}
-There is also another, more generic, way to reset a component's state.
+Ngoài ra còn có một cách khác, tổng quát hơn, để đặt lại state của một component.
-You might have seen `key`s when [rendering lists.](/learn/rendering-lists#keeping-list-items-in-order-with-key) Keys aren't just for lists! You can use keys to make React distinguish between any components. By default, React uses order within the parent ("first counter", "second counter") to discern between components. But keys let you tell React that this is not just a *first* counter, or a *second* counter, but a specific counter--for example, *Taylor's* counter. This way, React will know *Taylor's* counter wherever it appears in the tree!
+Bạn có thể đã thấy `key` khi [render danh sách.](/learn/rendering-lists#keeping-list-items-in-order-with-key) Keys không chỉ dành cho danh sách! Bạn có thể sử dụng keys để làm cho React phân biệt giữa bất kỳ component nào. Theo mặc định, React sử dụng thứ tự trong parent ("counter đầu tiên", "counter thứ hai") để phân biệt giữa các component. Nhưng keys cho phép bạn nói với React rằng đây không chỉ là counter *đầu tiên*, hoặc counter *thứ hai*, mà là một counter cụ thể--ví dụ, counter *của Taylor*. Bằng cách này, React sẽ biết counter *của Taylor* bất cứ nơi nào nó xuất hiện trong cây!
-In this example, the two `
`s don't share state even though they appear in the same place in JSX:
+Trong ví dụ này, hai `
` không chia sẻ state mặc dù chúng xuất hiện ở cùng vị trí trong JSX:
@@ -999,7 +999,7 @@ h1 {
-Switching between Taylor and Sarah does not preserve the state. This is because **you gave them different `key`s:**
+Việc chuyển đổi giữa Taylor và Sarah không bảo tồn state. Điều này vì **bạn đã trao cho chúng các `key` khác nhau:**
```js
{isPlayerA ? (
@@ -1009,19 +1009,19 @@ Switching between Taylor and Sarah does not preserve the state. This is because
)}
```
-Specifying a `key` tells React to use the `key` itself as part of the position, instead of their order within the parent. This is why, even though you render them in the same place in JSX, React sees them as two different counters, and so they will never share state. Every time a counter appears on the screen, its state is created. Every time it is removed, its state is destroyed. Toggling between them resets their state over and over.
+Chỉ định một `key` nói với React sử dụng chính `key` đó như một phần của vị trí, thay vì thứ tự của chúng trong parent. Đây là lý do tại sao, mặc dù bạn render chúng ở cùng vị trí trong JSX, React coi chúng là hai counter khác nhau, và vì vậy chúng sẽ không bao giờ chia sẻ state. Mỗi khi một counter xuất hiện trên màn hình, state của nó được tạo. Mỗi khi nó bị xóa, state của nó bị hủy. Việc chuyển đổi giữa chúng đặt lại state của chúng lặp đi lặp lại.
-Remember that keys are not globally unique. They only specify the position *within the parent*.
+Hãy nhớ rằng keys không phải là duy nhất toàn cầu. Chúng chỉ chỉ định vị trí *trong parent*.
-### Resetting a form with a key {/*resetting-a-form-with-a-key*/}
+### Đặt lại một form với một key {/*resetting-a-form-with-a-key*/}
-Resetting state with a key is particularly useful when dealing with forms.
+Đặt lại state với một key đặc biệt hữu ích khi xử lý forms.
-In this chat app, the `
` component contains the text input state:
+Trong ứng dụng chat này, component `` chứa state text input:
@@ -1116,17 +1116,17 @@ textarea {
-Try entering something into the input, and then press "Alice" or "Bob" to choose a different recipient. You will notice that the input state is preserved because the `` is rendered at the same position in the tree.
+Thử nhập một cái gì đó vào input, sau đó nhấn "Alice" hoặc "Bob" để chọn người nhận khác. Bạn sẽ nhận thấy rằng state input được bảo tồn vì `` được render ở cùng vị trí trong cây.
-**In many apps, this may be the desired behavior, but not in a chat app!** You don't want to let the user send a message they already typed to a wrong person due to an accidental click. To fix it, add a `key`:
+**Trong nhiều ứng dụng, đây có thể là hành vi mong muốn, nhưng không phải trong ứng dụng chat!** Bạn không muốn để người dùng gửi tin nhắn mà họ đã gõ đến người sai vì click nhầm. Để sửa điều này, hãy thêm một `key`:
```js
```
-This ensures that when you select a different recipient, the `Chat` component will be recreated from scratch, including any state in the tree below it. React will also re-create the DOM elements instead of reusing them.
+Điều này đảm bảo rằng khi bạn chọn một người nhận khác, component `Chat` sẽ được tạo lại từ đầu, bao gồm bất kỳ state nào trong cây bên dưới nó. React cũng sẽ tạo lại các DOM elements thay vì tái sử dụng chúng.
-Now switching the recipient always clears the text field:
+Giờ việc chuyển đổi người nhận luôn xóa trường text:
@@ -1223,24 +1223,33 @@ textarea {
-#### Preserving state for removed components {/*preserving-state-for-removed-components*/}
+#### Bảo tồn state cho các component đã bị xóa {/*preserving-state-for-removed-components*/}
-In a real chat app, you'd probably want to recover the input state when the user selects the previous recipient again. There are a few ways to keep the state "alive" for a component that's no longer visible:
+Trong một ứng dụng chat thực tế, bạn có thể muốn khôi phục state input khi người dùng chọn lại người nhận trước đó. Có một vài cách để giữ state "sống" cho một component không còn hiển thị:
-- You could render _all_ chats instead of just the current one, but hide all the others with CSS. The chats would not get removed from the tree, so their local state would be preserved. This solution works great for simple UIs. But it can get very slow if the hidden trees are large and contain a lot of DOM nodes.
-- You could [lift the state up](/learn/sharing-state-between-components) and hold the pending message for each recipient in the parent component. This way, when the child components get removed, it doesn't matter, because it's the parent that keeps the important information. This is the most common solution.
-- You might also use a different source in addition to React state. For example, you probably want a message draft to persist even if the user accidentally closes the page. To implement this, you could have the `Chat` component initialize its state by reading from the [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), and save the drafts there too.
+- Bạn có thể render _tất cả_ các cuộc chat thay vì chỉ cuộc chat hiện tại, nhưng ẩn tất cả những cái khác với CSS. Các cuộc chat sẽ không bị xóa khỏi cây, vì vậy state cục bộ của chúng sẽ được bảo tồn. Giải pháp này hoạt động tuyệt vời cho UI đơn giản. Nhưng nó có thể trở nên rất chậm nếu các cây ẩn lớn và chứa nhiều DOM nodes.
+- Bạn có thể [lift state lên](/learn/sharing-state-between-components) và giữ tin nhắn đang chờ cho mỗi người nhận trong component cha. Bằng cách này, khi các component con bị xóa, không thành vấn đề, vì chính component cha giữ thông tin quan trọng. Đây là giải pháp phổ biến nhất.
+- Bạn cũng có thể sử dụng một nguồn khác ngoài React state. Ví dụ, bạn có thể muốn một bản nháp tin nhắn vẫn tồn tại ngay cả khi người dùng vô tình đóng trang. Để triển khai điều này, bạn có thể để component `Chat` khởi tạo state của nó bằng cách đọc từ [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), và lưu các bản nháp ở đó.
-No matter which strategy you pick, a chat _with Alice_ is conceptually distinct from a chat _with Bob_, so it makes sense to give a `key` to the `` tree based on the current recipient.
+Bất kể bạn chọn chiến lược nào, một cuộc chat *với Alice* về mặt khái niệm khác với một cuộc chat *với Bob*, vì vậy việc trao một `key` cho cây `` dựa trên người nhận hiện tại là hợp lý.
-- React keeps state for as long as the same component is rendered at the same position.
-- State is not kept in JSX tags. It's associated with the tree position in which you put that JSX.
-- You can force a subtree to reset its state by giving it a different key.
-- Don't nest component definitions, or you'll reset state by accident.
+- React giữ state miễn là cùng một component được render ở cùng vị trí.
+- State không được giữ trong các thẻ JSX. Nó được liên kết với vị trí cây mà bạn đặt JSX đó.
+- Bạn có thể buộc một cây con đặt lại state của nó bằng cách trao cho nó một key khác.
+- Đừng lồng các định nghĩa component, hoặc bạn sẽ đặt lại state một cách vô tình.
+
+
+
+
+
+- React giữ state miễn là cùng một component được render ở cùng vị trí.
+- State không được giữ trong các thẻ JSX. Nó được liên kết với vị trí cây mà bạn đặt JSX đó.
+- Bạn có thể buộc một cây con đặt lại state của nó bằng cách trao cho nó một key khác.
+- Đừng lồng các định nghĩa component, hoặc bạn sẽ đặt lại state một cách vô tình.
@@ -1248,9 +1257,9 @@ No matter which strategy you pick, a chat _with Alice_ is conceptually distinct
-#### Fix disappearing input text {/*fix-disappearing-input-text*/}
+#### Sửa text input biến mất {/*fix-disappearing-input-text*/}
-This example shows a message when you press the button. However, pressing the button also accidentally resets the input. Why does this happen? Fix it so that pressing the button does not reset the input text.
+Ví dụ này hiển thị một tin nhắn khi bạn nhấn button. Tuy nhiên, việc nhấn button cũng vô tình đặt lại input. Tại sao điều này xảy ra? Hãy sửa nó để việc nhấn button không đặt lại text input.
@@ -1299,9 +1308,9 @@ textarea { display: block; margin: 10px 0; }
-The problem is that `Form` is rendered in different positions. In the `if` branch, it is the second child of the ``, but in the `else` branch, it is the first child. Therefore, the component type in each position changes. The first position changes between holding a `p` and a `Form`, while the second position changes between holding a `Form` and a `button`. React resets the state every time the component type changes.
+Vấn đề là `Form` được render ở các vị trí khác nhau. Trong nhánh `if`, nó là con thứ hai của `
`, nhưng trong nhánh `else`, nó là con đầu tiên. Do đó, loại component ở mỗi vị trí thay đổi. Vị trí đầu tiên thay đổi giữa việc chứa một `p` và một `Form`, trong khi vị trí thứ hai thay đổi giữa việc chứa một `Form` và một `button`. React đặt lại state mỗi khi loại component thay đổi.
-The easiest solution is to unify the branches so that `Form` always renders in the same position:
+Giải pháp dễ nhất là thống nhất các nhánh để `Form` luôn render ở cùng vị trí:
@@ -1347,7 +1356,7 @@ textarea { display: block; margin: 10px 0; }
-Technically, you could also add `null` before `
` in the `else` branch to match the `if` branch structure:
+Về mặt kỹ thuật, bạn cũng có thể thêm `null` trước `
` trong nhánh `else` để khớp với cấu trúc nhánh `if`:
@@ -1395,19 +1404,19 @@ textarea { display: block; margin: 10px 0; }
-This way, `Form` is always the second child, so it stays in the same position and keeps its state. But this approach is much less obvious and introduces a risk that someone else will remove that `null`.
+Bằng cách này, `Form` luôn là con thứ hai, vì vậy nó ở cùng vị trí và giữ state của nó. Nhưng cách tiếp cận này ít rõ ràng hơn nhiều và tạo ra rủi ro rằng người khác sẽ xóa `null` đó.
-#### Swap two form fields {/*swap-two-form-fields*/}
+#### Hoán đổi hai trường form {/*swap-two-form-fields*/}
-This form lets you enter first and last name. It also has a checkbox controlling which field goes first. When you tick the checkbox, the "Last name" field will appear before the "First name" field.
+Form này cho phép bạn nhập họ và tên. Nó cũng có một checkbox kiểm soát trường nào đi trước. Khi bạn tick vào checkbox, trường "Last name" sẽ xuất hiện trước trường "First name".
-It almost works, but there is a bug. If you fill in the "First name" input and tick the checkbox, the text will stay in the first input (which is now "Last name"). Fix it so that the input text *also* moves when you reverse the order.
+Nó gần như hoạt động, nhưng có một bug. Nếu bạn điền vào input "First name" và tick vào checkbox, text sẽ vẫn ở input đầu tiên (giờ là "Last name"). Hãy sửa nó để text input *cũng* di chuyển khi bạn đảo ngược thứ tự.
-It seems like for these fields, their position within the parent is not enough. Is there some way to tell React how to match up the state between re-renders?
+Có vẻ như đối với những trường này, vị trí của chúng trong parent là không đủ. Có cách nào để nói với React cách khớp state giữa các lần render không?
@@ -1471,7 +1480,7 @@ label { display: block; margin: 10px 0; }
-Give a `key` to both `` components in both `if` and `else` branches. This tells React how to "match up" the correct state for either `` even if their order within the parent changes:
+Trao một `key` cho cả hai component `` trong cả nhánh `if` và `else`. Điều này nói với React cách "khớp" state chính xác cho bất kỳ `` nào ngay cả khi thứ tự của chúng trong parent thay đổi:
@@ -1533,11 +1542,11 @@ label { display: block; margin: 10px 0; }
-#### Reset a detail form {/*reset-a-detail-form*/}
+#### Đặt lại một detail form {/*reset-a-detail-form*/}
-This is an editable contact list. You can edit the selected contact's details and then either press "Save" to update it, or "Reset" to undo your changes.
+Đây là một danh sách liên hệ có thể chỉnh sửa. Bạn có thể chỉnh sửa thông tin chi tiết của liên hệ đã chọn rồi nhấn "Save" để cập nhật nó, hoặc "Reset" để hoàn tác các thay đổi.
-When you select a different contact (for example, Alice), the state updates but the form keeps showing the previous contact's details. Fix it so that the form gets reset when the selected contact changes.
+Khi bạn chọn một liên hệ khác (ví dụ, Alice), state được cập nhật nhưng form vẫn hiển thị thông tin chi tiết của liên hệ trước đó. Hãy sửa nó để form được đặt lại khi liên hệ được chọn thay đổi.
@@ -1689,7 +1698,7 @@ button {
-Give `key={selectedId}` to the `EditContact` component. This way, switching between different contacts will reset the form:
+Trao `key={selectedId}` cho component `EditContact`. Bằng cách này, việc chuyển đổi giữa các liên hệ khác nhau sẽ đặt lại form:
@@ -1842,13 +1851,13 @@ button {
-#### Clear an image while it's loading {/*clear-an-image-while-its-loading*/}
+#### Xóa một hình ảnh khi nó đang loading {/*clear-an-image-while-its-loading*/}
-When you press "Next", the browser starts loading the next image. However, because it's displayed in the same `
` tag, by default you would still see the previous image until the next one loads. This may be undesirable if it's important for the text to always match the image. Change it so that the moment you press "Next", the previous image immediately clears.
+Khi bạn nhấn "Next", trình duyệt bắt đầu loading hình ảnh tiếp theo. Tuy nhiên, vì nó được hiển thị trong cùng thẻ `
`, theo mặc định bạn vẫn sẽ thấy hình ảnh trước đó cho đến khi hình tiếp theo tải xong. Điều này có thể không mong muốn nếu việc text luôn khớp với hình ảnh là quan trọng. Hãy thay đổi nó để ngay khi bạn nhấn "Next", hình ảnh trước đó ngay lập tức được xóa.
-Is there a way to tell React to re-create the DOM instead of reusing it?
+Có cách nào để nói với React tạo lại DOM thay vì tái sử dụng nó không?
@@ -1918,7 +1927,7 @@ img { width: 150px; height: 150px; }
-You can provide a `key` to the `
` tag. When that `key` changes, React will re-create the `
` DOM node from scratch. This causes a brief flash when each image loads, so it's not something you'd want to do for every image in your app. But it makes sense if you want to ensure the image always matches the text.
+Bạn có thể cung cấp một `key` cho thẻ `
`. Khi `key` đó thay đổi, React sẽ tạo lại DOM node `
` từ đầu. Điều này gây ra một flash ngắn khi mỗi hình ảnh tải, vì vậy đó không phải là điều bạn muốn làm cho mọi hình ảnh trong ứng dụng của mình. Nhưng nó hợp lý nếu bạn muốn đảm bảo hình ảnh luôn khớp với text.
@@ -1986,11 +1995,11 @@ img { width: 150px; height: 150px; }
-#### Fix misplaced state in the list {/*fix-misplaced-state-in-the-list*/}
+#### Sửa state bị đặt nhầm chỗ trong danh sách {/*fix-misplaced-state-in-the-list*/}
-In this list, each `Contact` has state that determines whether "Show email" has been pressed for it. Press "Show email" for Alice, and then tick the "Show in reverse order" checkbox. You will notice that it's _Taylor's_ email that is expanded now, but Alice's--which has moved to the bottom--appears collapsed.
+Trong danh sách này, mỗi `Contact` có state xác định liệu "Show email" đã được nhấn cho nó hay chưa. Nhấn "Show email" cho Alice, sau đó tick vào checkbox "Show in reverse order". Bạn sẽ nhận thấy rằng email của _Taylor_ được mở rộng bây giờ, nhưng Alice--đã di chuyển xuống dưới--xuất hiện thu gọn.
-Fix it so that the expanded state is associated with each contact, regardless of the chosen ordering.
+Hãy sửa nó để state mở rộng được liên kết với mỗi liên hệ, bất kể thứ tự được chọn.
@@ -2080,16 +2089,16 @@ button {
-The problem is that this example was using index as a `key`:
+Vấn đề là ví dụ này đang sử dụng index như một `key`:
```js
{displayedContacts.map((contact, i) =>
```
-However, you want the state to be associated with _each particular contact_.
+Tuy nhiên, bạn muốn state được liên kết với *mỗi liên hệ cụ thể*.
-Using the contact ID as a `key` instead fixes the issue:
+Sử dụng ID của contact như một `key` thay vào đó sẽ sửa vấn đề:
@@ -2177,7 +2186,7 @@ button {
-State is associated with the tree position. A `key` lets you specify a named position instead of relying on order.
+State được liên kết với vị trí cây. Một `key` cho phép bạn chỉ định một vị trí được đặt tên thay vì dựa vào thứ tự.