diff --git a/beta/src/content/apis/react/cloneElement.md b/beta/src/content/apis/react/cloneElement.md
index fa9d341f..114553d8 100644
--- a/beta/src/content/apis/react/cloneElement.md
+++ b/beta/src/content/apis/react/cloneElement.md
@@ -2,19 +2,693 @@
title: cloneElement
---
-
+
-This section is incomplete, please see the old docs for [cloneElement.](https://reactjs.org/docs/react-api.html#cloneelement)
-
-
+Using `cloneElement` is uncommon and can lead to fragile code. [See common alternatives.](#alternatives)
+
+`cloneElement` lets you create a new React element using another element as a starting point.
+
```js
-React.cloneElement(element, [config], [...children])
+const clonedElement = cloneElement(element, props, ...children)
```
+
+---
+
+## Usage {/*usage*/}
+
+### Overriding props of an element {/*overriding-props-of-an-element*/}
+
+To override the props of some React element, pass it to `cloneElement` with the props you want to override:
+
+```js [[1, 5, ""], [2, 6, "{ isHighlighted: true }"], [3, 4, "clonedElement"]]
+import { clonedElement } from 'react';
+
+// ...
+const clonedElement = cloneElement(
+ ,
+ { isHighlighted: true }
+);
+```
+
+Here, the resulting cloned element will be ``.
+
+**Let's walk through an example to see when it's useful.**
+
+Imagine a `List` component that renders its [`children`](/learn/passing-props-to-a-component#passing-jsx-as-children) as a list of selectable rows with a "Next" button that changes which row is selected. The `List` component needs to render the selected `Row` differently, so it clones every `` child that it has received, and adds an extra `isHighlighted: true` or `isHighlighted: false` prop:
+
+```js {6-8}
+export default function List({ children }) {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ return (
+
+ {Children.map(children, (child, index) =>
+ cloneElement(child, {
+ isHighlighted: index === selectedIndex
+ })
+ )}
+```
+
+Let's say the original JSX received by `List` looks like this:
+
+```js {2-4}
+
+
+
+
+
+```
+
+By cloning its children, the `List` can pass extra information to every `Row` inside. The result looks like this:
+
+```js {4,8,12}
+
+
+
+
+
+```
+
+Notice how pressing "Next" updates the state of the `List`, and highlights a different row:
+
+
+
+```js
+import List from './List.js';
+import Row from './Row.js';
+import { products } from './data.js';
+
+export default function App() {
+ return (
+
+ {products.map(product =>
+
+ )}
+
+ );
+}
+```
+
+```js List.js active
+import { Children, cloneElement, useState } from 'react';
+
+export default function List({ children }) {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ return (
+
+ );
+}
+```
+
+```js data.js
+export const products = [
+ { title: 'Cabbage', id: 1 },
+ { title: 'Garlic', id: 2 },
+ { title: 'Apple', id: 3 },
+];
+```
+
+```css
+.List {
+ display: flex;
+ flex-direction: column;
+ border: 2px solid grey;
+ padding: 5px;
+}
+
+.Row {
+ border: 2px dashed black;
+ padding: 5px;
+ margin: 5px;
+}
+
+.RowHighlighted {
+ background: #ffa;
+}
+
+button {
+ height: 40px;
+ font-size: 20px;
+}
+```
+
+
+
+To summarize, the `List` cloned the `` elements it received and added an extra prop to them.
+
+
+
+Cloning children makes it hard to tell how the data flows through your app. Try one of the [alternatives.](#alternatives)
+
+
+
+---
+
+## Alternatives {/*alternatives*/}
+
+### Passing data with a render prop {/*passing-data-with-a-render-prop*/}
+
+Instead of using `cloneElement`, consider accepting a *render prop* like `renderItem`. Here, `List` receives `renderItem` as a prop. `List` calls `renderItem` for every item and passes `isHighlighted` as an argument:
+
+```js {1,7}
+export default function List({ items, renderItem }) {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ return (
+
+ {items.map((item, index) => {
+ const isHighlighted = index === selectedIndex;
+ return renderItem(item, isHighlighted);
+ })}
+```
+
+The `renderItem` prop is called a "render prop" because it's a prop that specifies how to render something. For example, you can pass a `renderItem` implementation that renders a `` with the given `isHighlighted` value:
+
+```js {3,7}
+
+
+ }
+/>
+```
+
+The end result is the same as with `cloneElement`:
+
+```js {4,8,12}
+
+
+
+
+
+```
+
+However, you can clearly trace where the `isHighlighted` value is coming from.
+
+
+
+```js
+import List from './List.js';
+import Row from './Row.js';
+import { products } from './data.js';
+
+export default function App() {
+ return (
+
+
+ }
+ />
+ );
+}
+```
+
+```js List.js active
+import { useState } from 'react';
+
+export default function List({ items, renderItem }) {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ return (
+
+ );
+}
+```
+
+```js Row.js
+import { useContext } from 'react';
+import { HighlightContext } from './HighlightContext.js';
+
+export default function Row({ title }) {
+ const isHighlighted = useContext(HighlightContext);
+ return (
+
+ {title}
+
+ );
+}
+```
+
+```js HighlightContext.js
+import { createContext } from 'react';
+
+export const HighlightContext = createContext(false);
+```
+
+```js data.js
+export const products = [
+ { title: 'Cabbage', id: 1 },
+ { title: 'Garlic', id: 2 },
+ { title: 'Apple', id: 3 },
+];
+```
+
+```css
+.List {
+ display: flex;
+ flex-direction: column;
+ border: 2px solid grey;
+ padding: 5px;
+}
+
+.Row {
+ border: 2px dashed black;
+ padding: 5px;
+ margin: 5px;
+}
+
+.RowHighlighted {
+ background: #ffa;
+}
+
+button {
+ height: 40px;
+ font-size: 20px;
+}
+```
+
+
+
+[Learn more about passing data through context.](/apis/react/useContext#passing-data-deeply-into-the-tree)
+
+---
+
+### Extracting logic into a custom Hook {/*extracting-logic-into-a-custom-hook*/}
+
+Another approach you can try is to extract the "non-visual" logic into your own Hook, and use the information returned by your Hook to decide what to render. For example, you could write a `useList` custom Hook like this:
+
+```js
+import { useState } from 'react';
+
+export default function useList(items) {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+
+ function onNext() {
+ setSelectedIndex(i =>
+ (i + 1) % items.length
+ );
+ }
+
+ const selected = items[selectedIndex];
+ return [selected, onNext];
+}
+```
+
+Then you could use it like this:
+
+```js {2,9,13}
+export default function App() {
+ const [selected, onNext] = useList(products);
+ return (
+
+ {products.map(product =>
+
+ )}
+
+
+
+ );
+}
+```
+
+The data flow is explicit, but the state is inside the `useList` custom Hook that you can use from any component:
+
+
+
+```js
+import Row from './Row.js';
+import useList from './useList.js';
+import { products } from './data.js';
+
+export default function App() {
+ const [selected, onNext] = useList(products);
+ return (
+
+ );
+}
+```
+
+```js data.js
+export const products = [
+ { title: 'Cabbage', id: 1 },
+ { title: 'Garlic', id: 2 },
+ { title: 'Apple', id: 3 },
+];
+```
+
+```css
+.List {
+ display: flex;
+ flex-direction: column;
+ border: 2px solid grey;
+ padding: 5px;
+}
+
+.Row {
+ border: 2px dashed black;
+ padding: 5px;
+ margin: 5px;
+}
+
+.RowHighlighted {
+ background: #ffa;
+}
+
+button {
+ height: 40px;
+ font-size: 20px;
+}
+```
+
+
+
+This approach is particularly useful if you want to reuse this logic between different components.
+
+---
+
+## Reference {/*reference*/}
+
+### `cloneElement(element, props, ...children)` {/*cloneelement*/}
+
+Call `cloneElement` to create a React element based on the `element`, but with different `props` and `children`:
+
+```js
+import { clonedElement } from 'react';
+
+// ...
+const clonedElement = cloneElement(
+
+ Hello
+ ,
+ { isHighlighted: true },
+ 'Goodbye'
+);
+
+console.log(clonedElement); // Goodbye
+```
+
+[See more examples above.](#usage)
+
+#### Parameters {/*parameters*/}
+
+* `element`: The `element` argument must be a valid React element. For example, it could be a JSX node like ``, the result of calling [`createElement`](/apis/react/createElement), or the result of another `cloneElement` call.
+
+* `props`: The `props` argument must either be an object or `null`. If you pass `null`, the cloned element will retain all of the original `element.props`. Otherwise, for every prop in the `props` object, the returned element will "prefer" the value from `props` over the value from `element.props`. The rest of the props will be filled from the original `element.props`. If you pass `props.key` or `props.ref`, they will replace the original ones.
+
+* **optional** `...children`: Zero or more child nodes. They can be any React nodes, including React elements, strings, numbers, [portals](/apis/react-dom/createPortal), empty nodes (`null`, `undefined`, `true`, and `false`), and arrays of React nodes. If you don't pass any `...children` arguments, the original `element.props.children` will be preserved.
+
+#### Returns {/*returns*/}
+
+`cloneElement` returns a React element object with a few properties:
+
+* `type`: Same as `element.type`.
+* `props`: The result of shallowly merging `element.props` with the overriding `props` you have passed.
+* `ref`: The original `element.ref`, unless it was overridden by `props.ref`.
+* `key`: The original `element.key`, unless it was overridden by `props.key`.
+
+Usually, you'll return the element from your component or make it a child of another element. Although you may read the element's properties, it's best to treat every element as opaque after it's created, and only render it.
+
+#### Caveats {/*caveats*/}
+
+* Cloning an element **does not modify the original element.**
+
+* You should only **pass children as multiple arguments to `createElement` if they are all statically known,** like `cloneElement(element, null, child1, child2, child3)`. If your children are dynamic, pass the entire array as the third argument: `cloneElement(element, null, listItems)`. This ensures that React will [warn you about missing `key`s](/learn/rendering-lists#keeping-list-items-in-order-with-key) for any dynamic lists. For static lists this is not necessary because they never reorder.
+
+* `cloneElement` makes it harder to trace the data flow, so **try the [alternatives](/#alternatives) instead.**
diff --git a/beta/src/sidebarReference.json b/beta/src/sidebarReference.json
index c7396afd..a2c94401 100644
--- a/beta/src/sidebarReference.json
+++ b/beta/src/sidebarReference.json
@@ -17,8 +17,7 @@
},
{
"title": "cloneElement",
- "path": "/apis/react/cloneElement",
- "wip": true
+ "path": "/apis/react/cloneElement"
},
{
"title": "Component",