diff --git a/beta/public/images/docs/diagrams/preserving_state_add_component.dark.svg b/beta/public/images/docs/diagrams/preserving_state_add_component.dark.svg new file mode 100644 index 00000000..adaa981b --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_add_component.dark.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_add_component.svg b/beta/public/images/docs/diagrams/preserving_state_add_component.svg new file mode 100644 index 00000000..48a56f37 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_add_component.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_position_p1.dark.svg b/beta/public/images/docs/diagrams/preserving_state_diff_position_p1.dark.svg new file mode 100644 index 00000000..5d2fd114 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_position_p1.dark.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_position_p1.svg b/beta/public/images/docs/diagrams/preserving_state_diff_position_p1.svg new file mode 100644 index 00000000..17bcc9f2 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_position_p1.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_position_p2.dark.svg b/beta/public/images/docs/diagrams/preserving_state_diff_position_p2.dark.svg new file mode 100644 index 00000000..582739f0 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_position_p2.dark.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_position_p2.svg b/beta/public/images/docs/diagrams/preserving_state_diff_position_p2.svg new file mode 100644 index 00000000..2348598b --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_position_p2.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_position_p3.dark.svg b/beta/public/images/docs/diagrams/preserving_state_diff_position_p3.dark.svg new file mode 100644 index 00000000..355e8ded --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_position_p3.dark.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_position_p3.svg b/beta/public/images/docs/diagrams/preserving_state_diff_position_p3.svg new file mode 100644 index 00000000..d7bb3c28 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_position_p3.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_pt1.dark.svg b/beta/public/images/docs/diagrams/preserving_state_diff_pt1.dark.svg new file mode 100644 index 00000000..2cfc2d66 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_pt1.dark.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_pt1.svg b/beta/public/images/docs/diagrams/preserving_state_diff_pt1.svg new file mode 100644 index 00000000..a0258e85 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_pt1.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_pt2.dark.svg b/beta/public/images/docs/diagrams/preserving_state_diff_pt2.dark.svg new file mode 100644 index 00000000..0d64ce97 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_pt2.dark.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_pt2.svg b/beta/public/images/docs/diagrams/preserving_state_diff_pt2.svg new file mode 100644 index 00000000..2f7936b8 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_pt2.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_same_pt1.dark.svg b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt1.dark.svg new file mode 100644 index 00000000..76d0b65a --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt1.dark.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_same_pt1.svg b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt1.svg new file mode 100644 index 00000000..883dd43b --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt1.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_same_pt2.dark.svg b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt2.dark.svg new file mode 100644 index 00000000..91bb862e --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt2.dark.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_diff_same_pt2.svg b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt2.svg new file mode 100644 index 00000000..800551d8 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_diff_same_pt2.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_dom_tree.dark.svg b/beta/public/images/docs/diagrams/preserving_state_dom_tree.dark.svg new file mode 100644 index 00000000..5b9020c5 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_dom_tree.dark.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_dom_tree.svg b/beta/public/images/docs/diagrams/preserving_state_dom_tree.svg new file mode 100644 index 00000000..836000fa --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_dom_tree.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_increment.dark.svg b/beta/public/images/docs/diagrams/preserving_state_increment.dark.svg new file mode 100644 index 00000000..505afc6e --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_increment.dark.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_increment.svg b/beta/public/images/docs/diagrams/preserving_state_increment.svg new file mode 100644 index 00000000..b85f2f70 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_increment.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_remove_component.dark.svg b/beta/public/images/docs/diagrams/preserving_state_remove_component.dark.svg new file mode 100644 index 00000000..281da2e1 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_remove_component.dark.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_remove_component.svg b/beta/public/images/docs/diagrams/preserving_state_remove_component.svg new file mode 100644 index 00000000..d0c6057b --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_remove_component.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_same_component.dark.svg b/beta/public/images/docs/diagrams/preserving_state_same_component.dark.svg new file mode 100644 index 00000000..beded1be --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_same_component.dark.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_same_component.svg b/beta/public/images/docs/diagrams/preserving_state_same_component.svg new file mode 100644 index 00000000..f638f230 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_same_component.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_tree.dark.svg b/beta/public/images/docs/diagrams/preserving_state_tree.dark.svg new file mode 100644 index 00000000..8f856013 --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_tree.dark.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/diagrams/preserving_state_tree.svg b/beta/public/images/docs/diagrams/preserving_state_tree.svg new file mode 100644 index 00000000..7a404ded --- /dev/null +++ b/beta/public/images/docs/diagrams/preserving_state_tree.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/beta/public/images/docs/illustrations/i_keys-in-trees.png b/beta/public/images/docs/illustrations/i_keys-in-trees.png deleted file mode 100644 index 55d864f9..00000000 Binary files a/beta/public/images/docs/illustrations/i_keys-in-trees.png and /dev/null differ diff --git a/beta/public/images/docs/illustrations/i_react-is-blind-to-ui-swap.png b/beta/public/images/docs/illustrations/i_react-is-blind-to-ui-swap.png deleted file mode 100644 index d20511be..00000000 Binary files a/beta/public/images/docs/illustrations/i_react-is-blind-to-ui-swap.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_jsx-to-tree.png b/beta/public/images/docs/sketches/s_jsx-to-tree.png deleted file mode 100644 index 0b7f845e..00000000 Binary files a/beta/public/images/docs/sketches/s_jsx-to-tree.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_react-dom-tree.png b/beta/public/images/docs/sketches/s_react-dom-tree.png deleted file mode 100644 index b33bf0e4..00000000 Binary files a/beta/public/images/docs/sketches/s_react-dom-tree.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_remove-ui.png b/beta/public/images/docs/sketches/s_remove-ui.png deleted file mode 100644 index d2307cf2..00000000 Binary files a/beta/public/images/docs/sketches/s_remove-ui.png and /dev/null differ diff --git a/beta/public/images/docs/sketches/s_ui-swap.png b/beta/public/images/docs/sketches/s_ui-swap.png deleted file mode 100644 index ce96d7e0..00000000 Binary files a/beta/public/images/docs/sketches/s_ui-swap.png and /dev/null differ diff --git a/beta/src/components/MDX/Diagram.tsx b/beta/src/components/MDX/Diagram.tsx index ead42694..3388ce9d 100644 --- a/beta/src/components/MDX/Diagram.tsx +++ b/beta/src/components/MDX/Diagram.tsx @@ -31,7 +31,7 @@ export function Diagram({ captionPosition, }: DiagramProps) { return ( -
+
{captionPosition === 'top' && }
+
{children}
); diff --git a/beta/src/pages/learn/preserving-and-resetting-state.md b/beta/src/pages/learn/preserving-and-resetting-state.md index 6356630f..16da2f9d 100644 --- a/beta/src/pages/learn/preserving-and-resetting-state.md +++ b/beta/src/pages/learn/preserving-and-resetting-state.md @@ -23,7 +23,15 @@ Browsers use many tree structures to model UI. The [DOM](https://developer.mozil React also uses tree structures to manage and model the UI you make. React makes **UI trees** from your JSX. Then React DOM updates the browser DOM elements to match that UI tree. (React Native translates these trees into elements specific to mobile platforms.) -React takes components, turns them into UI tree structures, and ReactDOM turns them into HTML in your browser using the DOM. + + + + +From components, React creates a UI Tree which React DOM uses to render the DOM. + + + + ## State is tied to a position in the tree {/*state-is-tied-to-a-position-in-the-tree*/} @@ -94,9 +102,17 @@ label { -Here's how these look as a tree: +Here's how these look as a tree: + + + + + +React Tree + + -The JSX become a tree. + **These are two separate counters because each is rendered at its own position in the tree.** You don't usually have to think about these positions to use React, but it can be useful to understand how it works. @@ -160,7 +176,21 @@ function Counter() { -React will only keep the state around for as long as you render the same component at the same position. To see this, increment both counters, then clear "Render the second counter" checkbox, and then tick it again: +As you can see, when one counter is updated, only the state for that component is updated: + + + + + + +Updating state + + + + + + +React will keep the state around for as long as you render the same component at the same position. To see this, increment both counters, then remove the second component by unchecking "Render the second counter" checkbox, and then add it back by ticking it again: @@ -236,11 +266,27 @@ label { Notice how the moment you stop rendering the second counter, its state disappears completely. That's because when React removes a component, it destroys its state. -React removes a component from the tree, it destroys its state as well + + + + +Deleting a component + + + + When you tick "Render the second counter," a second `Counter` and its state are initialized from scratch (`score = 0`) and added to the DOM. -When React adds UI to the DOM tree, it starts with all new state. + + + + +Adding a component + + + + **React preserves a component's state for as long as it's being rendered at its position in the UI tree.** If it gets removed, or a different component gets rendered at the same position, React discards its state. @@ -333,12 +379,18 @@ label { When you tick or clear the checkbox, the counter state does not get reset. Whether `isFancy` is `true` or `false`, you always have a `` as the first child of the `div` returned from the root `App` component: -React only sees the component and its position in the UI tree on render. + + -It's the same component at the same position, so from React's perspective, it's the same counter. +Since Counter is always in the same position, the count does not reset, event when isFancy state in the parent changes. + + + + - + +It's the same component at the same position, so from React's perspective, it's the same counter. @@ -527,7 +579,25 @@ 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. -Removing a component from the UI tree destroys its state. + + + + +When Counter changes to p, first the Counter is unmounted, then the p is mounted. + + + + + + + + + +When switching back, first the p is unmounted, then the Counter is mounted. + + + + 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: @@ -620,7 +690,25 @@ 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 `div` to a `section`. When the child `div` was removed from the DOM, the whole tree below it (including the `Counter` and its state) was destroyed as well. -If the first child isn't the same, forget about it! + + + + +When section changes to div, first the section is unmounted then the new div is mounted. + + + + + + + + + +When switching back, first the div is unmounted then the new section is mounted. + + + + 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. @@ -741,8 +829,6 @@ 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. - - 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. There are two ways to reset state when switching between them: @@ -827,7 +913,27 @@ 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`. - + + + + +Initial State + + + + + +Clicking "next" + + + + + +Clicking "next" again + + + + > Each `Counter`'s state gets destroyed each time its removed from the DOM. This is why they reset every time you click the button. @@ -921,8 +1027,6 @@ 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, from React's perspective, these are two different counters. As a result, 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. - - > Remember that keys are not globally unique. They only specify the position *within the parent*. ### Resetting a form with a key {/*resetting-a-form-with-a-key*/} @@ -2087,4 +2191,4 @@ State is associated with the tree position. A `key` lets you specify a named pos - \ No newline at end of file +