Skip to content

[18] Switch code samples to createRoot #4470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 19, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions beta/src/pages/learn/add-react-to-a-website.md
Original file line number Diff line number Diff line change
@@ -74,11 +74,12 @@ function LikeButton() {

### Step 4: Add your React Component to the page {/*step-4-add-your-react-component-to-the-page*/}

Lastly, add two lines to the bottom of **like_button.js**. These two lines of code find the `<div>` you added to your HTML in the first step and then display the "Like" button React component inside of it.
Lastly, add three lines to the bottom of **like_button.js**. These three lines of code find the `<div>` you added to your HTML in the first step, create a React app with it, and then display the "Like" button React component inside of it.

```js
const domContainer = document.getElementById('component-goes-here');
ReactDOM.render(React.createElement(LikeButton), domContainer);
const root = ReactDOM.createRoot(domContainer);
root.render(React.createElement(LikeButton));
```

**Congratulations! You have just rendered your first React component to your website!**
@@ -88,21 +89,21 @@ ReactDOM.render(React.createElement(LikeButton), domContainer);

#### You can reuse components! {/*you-can-reuse-components*/}

You might want to display a React component in multiple places on the same HTML page. This is most useful while React-powered parts of the page are isolated from each other. You can do this by calling `ReactDOM.render()` multiple times with multiple container elements.
You might want to display a React component in multiple places on the same HTML page. This is most useful while React-powered parts of the page are isolated from each other. You can do this by calling `ReactDOM.createRoot()` multiple times with multiple container elements.

1. In **index.html**, add an additional container element `<div id="component-goes-here-too"></div>`.
2. In **like_button.js**, add an additional `ReactDOM.render()` for the new container element:

```js {6,7,8,9}
ReactDOM.render(
React.createElement(LikeButton),
const root1 = ReactDOM.createRoot(
document.getElementById('component-goes-here')
);
root1.render(React.createElement(LikeButton));

ReactDOM.render(
React.createElement(LikeButton),
const root2 = ReactDOM.createRoot(
document.getElementById('component-goes-here-too')
);
root2.render(React.createElement(LikeButton));
```

Check out [an example that displays the "Like" button three times and passes some data to it](https://gist.github.com/rachelnabors/c0ea05cc33fbe75ad9bbf78e9044d7f8)!
@@ -157,8 +158,8 @@ Now you can use JSX in any `<script>` tag by adding `type="text/babel"` attribut

```jsx {1}
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>, document.getElementById('root') );
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<h1>Hello, world!</h1>);
</script>
```

7 changes: 4 additions & 3 deletions content/docs/add-react-to-a-website.md
Original file line number Diff line number Diff line change
@@ -77,14 +77,15 @@ Open **[this starter code](https://gist.github.com/gaearon/0b180827c190fe4fd98b4

After **[the starter code](https://gist.github.com/gaearon/0b180827c190fe4fd98b4c7f570ea4a8/raw/b9157ce933c79a4559d2aa9ff3372668cce48de7/LikeButton.js)**, add two lines to the bottom of `like_button.js`:

```js{3,4}
```js{3,4,5}
// ... the starter code you pasted ...

const domContainer = document.querySelector('#like_button_container');
ReactDOM.render(e(LikeButton), domContainer);
const root = ReactDOM.createRoot(domContainer);
root.render(e(LikeButton));
```

These two lines of code find the `<div>` we added to our HTML in the first step, and then display our "Like" button React component inside of it.
These three lines of code find the `<div>` we added to our HTML in the first step, create a React app with it, and then display our "Like" button React component inside of it.

### That's It! {#thats-it}

2 changes: 1 addition & 1 deletion content/docs/addons-shallow-renderer.md
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ Shallow testing currently has some limitations, namely not supporting refs.

You can think of the shallowRenderer as a "place" to render the component you're testing, and from which you can extract the component's output.

`shallowRenderer.render()` is similar to [`ReactDOM.render()`](/docs/react-dom.html#render) but it doesn't require DOM and only renders a single level deep. This means you can test components isolated from how their children are implemented.
`shallowRenderer.render()` is similar to [`root.render()`](/docs/react-dom-client.html#createroot) but it doesn't require DOM and only renders a single level deep. This means you can test components isolated from how their children are implemented.

### `shallowRenderer.getRenderOutput()` {#shallowrenderergetrenderoutput}

6 changes: 3 additions & 3 deletions content/docs/addons-test-utils.md
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ Here is how we can test it:

```js{3,20-22,29-31}
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOM from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import Counter from './Counter';

@@ -108,7 +108,7 @@ afterEach(() => {
it('can render and update a counter', () => {
// Test first render and componentDidMount
act(() => {
ReactDOM.render(<Counter />, container);
ReactDOM.createRoot(container).render(<Counter />);
});
const button = container.querySelector('button');
const label = container.querySelector('p');
@@ -304,7 +304,7 @@ Render a React element into a detached DOM node in the document. **This function

```js
const domContainer = document.createElement('div');
ReactDOM.render(element, domContainer);
ReactDOM.createRoot(domContainer).render(element);
```

> Note:
13 changes: 3 additions & 10 deletions content/docs/components-and-props.md
Original file line number Diff line number Diff line change
@@ -70,17 +70,15 @@ function Welcome(props) {
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(element);
```

**[Try it on CodePen](https://codepen.io/gaearon/pen/YGYmEG?editors=1010)**

Let's recap what happens in this example:

1. We call `ReactDOM.render()` with the `<Welcome name="Sara" />` element.
1. We call `root.render()` with the `<Welcome name="Sara" />` element.
2. React calls the `Welcome` component with `{name: 'Sara'}` as the props.
3. Our `Welcome` component returns a `<h1>Hello, Sara</h1>` element as the result.
4. React DOM efficiently updates the DOM to match `<h1>Hello, Sara</h1>`.
@@ -111,11 +109,6 @@ function App() {
</div>
);
}

ReactDOM.render(
<App />,
document.getElementById('root')
);
```

**[Try it on CodePen](https://codepen.io/gaearon/pen/KgQKPr?editors=1010)**
2 changes: 1 addition & 1 deletion content/docs/concurrent-mode-adoption.md
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ import ReactDOM from 'react-dom';
//
// You can opt into Concurrent Mode by writing:

ReactDOM.unstable_createRoot(
ReactDOM.createRoot(
document.getElementById('root')
).render(<App />);
```
4 changes: 2 additions & 2 deletions content/docs/forms.md
Original file line number Diff line number Diff line change
@@ -275,10 +275,10 @@ Specifying the `value` prop on a [controlled component](/docs/forms.html#control
The following code demonstrates this. (The input is locked at first but becomes editable after a short delay.)

```javascript
ReactDOM.render(<input value="hi" />, mountNode);
ReactDOM.createRoot(mountNode).render(<input value="hi" />);

setTimeout(function() {
ReactDOM.render(<input value={null} />, mountNode);
ReactDOM.createRoot(mountNode).render(<input value={null} />);
}, 1000);

```
5 changes: 0 additions & 5 deletions content/docs/handling-events.md
Original file line number Diff line number Diff line change
@@ -84,11 +84,6 @@ class Toggle extends React.Component {
);
}
}

ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/xEmzGg?editors=0010)
9 changes: 4 additions & 5 deletions content/docs/hello-world.md
Original file line number Diff line number Diff line change
@@ -8,11 +8,10 @@ next: introducing-jsx.html

The smallest React example looks like this:

```js
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
```jsx
ReactDOM
.createRoot(document.getElementById('root'))
.render(<h1>Hello, world!</h1>);
```

It displays a heading saying "Hello, world!" on the page.
4 changes: 2 additions & 2 deletions content/docs/hooks-faq.md
Original file line number Diff line number Diff line change
@@ -148,7 +148,7 @@ We'll test it using React DOM. To make sure that the behavior matches what happe

```js{3,20-22,29-31}
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOM from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import Counter from './Counter';

@@ -167,7 +167,7 @@ afterEach(() => {
it('can render and update a counter', () => {
// Test first render and effect
act(() => {
ReactDOM.render(<Counter />, container);
ReactDOM.createRoot(container).render(<Counter />);
});
const button = container.querySelector('button');
const label = container.querySelector('p');
11 changes: 6 additions & 5 deletions content/docs/implementation-notes.md
Original file line number Diff line number Diff line change
@@ -32,10 +32,11 @@ The reconciler itself doesn't have a public API. [Renderers](/docs/codebase-over
Let's consider the first time you mount a component:

```js
ReactDOM.render(<App />, rootEl);
const root = ReactDOM.createRoot(rootEl);
root.render(<App />);
```

React DOM will pass `<App />` along to the reconciler. Remember that `<App />` is a React element, that is, a description of *what* to render. You can think about it as a plain object:
`root.render` will pass `<App />` along to the reconciler. Remember that `<App />` is a React element, that is, a description of *what* to render. You can think about it as a plain object:

```js
console.log(<App />);
@@ -236,9 +237,9 @@ This is working but still far from how the reconciler is really implemented. The
The key feature of React is that you can re-render everything, and it won't recreate the DOM or reset the state:

```js
ReactDOM.render(<App />, rootEl);
root.render(<App />);
// Should reuse the existing DOM:
ReactDOM.render(<App />, rootEl);
root.render(<App />);
```

However, our implementation above only knows how to mount the initial tree. It can't perform updates on it because it doesn't store all the necessary information, such as all the `publicInstance`s, or which DOM `node`s correspond to which components.
@@ -412,7 +413,7 @@ If you're struggling to imagine how an internal instance tree is structured in m

<img src="../images/docs/implementation-notes-tree.png" width="500" style="max-width: 100%" alt="React DevTools tree" />

To complete this refactoring, we will introduce a function that mounts a complete tree into a container node, just like `ReactDOM.render()`. It returns a public instance, also like `ReactDOM.render()`:
To complete this refactoring, we will introduce a function that mounts a complete tree into a container node and a public instance:

```js
function mountTree(element, containerNode) {
40 changes: 14 additions & 26 deletions content/docs/integrating-with-other-libraries.md
Original file line number Diff line number Diff line change
@@ -190,9 +190,9 @@ class Chosen extends React.Component {

## Integrating with Other View Libraries {#integrating-with-other-view-libraries}

React can be embedded into other applications thanks to the flexibility of [`ReactDOM.render()`](/docs/react-dom.html#render).
React can be embedded into other applications thanks to the flexibility of [`createRoot()`](/docs/react-dom-client.html#createRoot).

Although React is commonly used at startup to load a single root React component into the DOM, `ReactDOM.render()` can also be called multiple times for independent parts of the UI which can be as small as a button, or as large as an app.
Although React is commonly used at startup to load a single root React component into the DOM, `root.render()` can also be called multiple times for independent parts of the UI which can be as small as a button, or as large as an app.

In fact, this is exactly how React is used at Facebook. This lets us write applications in React piece by piece, and combine them with our existing server-generated templates and other client-side code.

@@ -216,15 +216,9 @@ function Button() {
return <button id="btn">Say Hello</button>;
}

ReactDOM.render(
<Button />,
document.getElementById('container'),
function() {
$('#btn').click(function() {
alert('Hello!');
});
}
);
$('#btn').click(function() {
alert('Hello!');
});
```

From here you could start moving more logic into the component and begin adopting more common React practices. For example, in components it is best not to rely on IDs because the same component can be rendered multiple times. Instead, we will use the [React event system](/docs/handling-events.html) and register the click handler directly on the React `<button>` element:
@@ -240,44 +234,40 @@ function HelloButton() {
}
return <Button onClick={handleClick} />;
}

ReactDOM.render(
<HelloButton />,
document.getElementById('container')
);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/RVKbvW?editors=1010)

You can have as many such isolated components as you like, and use `ReactDOM.render()` to render them to different DOM containers. Gradually, as you convert more of your app to React, you will be able to combine them into larger components, and move some of the `ReactDOM.render()` calls up the hierarchy.
You can have as many such isolated components as you like, and use `ReactDOM.createRoot()` to render them to different DOM containers. Gradually, as you convert more of your app to React, you will be able to combine them into larger components, and move some of the `ReactDOM.createRoot()` calls up the hierarchy.

### Embedding React in a Backbone View {#embedding-react-in-a-backbone-view}

[Backbone](https://backbonejs.org/) views typically use HTML strings, or string-producing template functions, to create the content for their DOM elements. This process, too, can be replaced with rendering a React component.

Below, we will create a Backbone view called `ParagraphView`. It will override Backbone's `render()` function to render a React `<Paragraph>` component into the DOM element provided by Backbone (`this.el`). Here, too, we are using [`ReactDOM.render()`](/docs/react-dom.html#render):
Below, we will create a Backbone view called `ParagraphView`. It will override Backbone's `render()` function to render a React `<Paragraph>` component into the DOM element provided by Backbone (`this.el`). Here, too, we are using [`ReactDOM.createRoot()`](/docs/react-dom-client.html#createroot):

```js{1,5,8,12}
```js{1,5,8-9,13}
function Paragraph(props) {
return <p>{props.text}</p>;
}

const ParagraphView = Backbone.View.extend({
render() {
const text = this.model.get('text');
ReactDOM.render(<Paragraph text={text} />, this.el);
this.root = ReactDOM.createRoot(this.el);
this.root.render(<Paragraph text={text} />);
return this;
},
remove() {
ReactDOM.unmountComponentAtNode(this.el);
this.root.unmount();
Backbone.View.prototype.remove.call(this);
}
});
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/gWgOYL?editors=0010)

It is important that we also call `ReactDOM.unmountComponentAtNode()` in the `remove` method so that React unregisters event handlers and other resources associated with the component tree when it is detached.
It is important that we also call `root.unmount()` in the `remove` method so that React unregisters event handlers and other resources associated with the component tree when it is detached.

When a component is removed *from within* a React tree, the cleanup is performed automatically, but because we are removing the entire tree by hand, we must call this method.

@@ -428,10 +418,8 @@ function Example(props) {
}

const model = new Backbone.Model({ firstName: 'Frodo' });
ReactDOM.render(
<Example model={model} />,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Example model={model} />);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/PmWwwa?editors=0010)
10 changes: 0 additions & 10 deletions content/docs/introducing-jsx.md
Original file line number Diff line number Diff line change
@@ -35,11 +35,6 @@ In the example below, we declare a variable called `name` and then use it inside
```js{1,2}
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

ReactDOM.render(
element,
document.getElementById('root')
);
```

You can put any valid [JavaScript expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions) inside the curly braces in JSX. For example, `2 + 2`, `user.firstName`, or `formatName(user)` are all valid JavaScript expressions.
@@ -61,11 +56,6 @@ const element = (
Hello, {formatName(user)}!
</h1>
);

ReactDOM.render(
element,
document.getElementById('root')
);
```

**[Try it on CodePen](https://codepen.io/gaearon/pen/PGEjdG?editors=1010)**
38 changes: 7 additions & 31 deletions content/docs/lists-and-keys.md
Original file line number Diff line number Diff line change
@@ -33,13 +33,10 @@ const listItems = numbers.map((number) =>
);
```

We include the entire `listItems` array inside a `<ul>` element, and [render it to the DOM](/docs/rendering-elements.html#rendering-an-element-into-the-dom):
Then, we can include the entire `listItems` array inside a `<ul>` element:

```javascript{2}
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);
<ul>{listItems}</ul>
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/GjPyQr?editors=0011)
@@ -64,10 +61,8 @@ function NumberList(props) {
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<NumberList numbers={numbers} />);
```

When you run this code, you'll be given a warning that a key should be provided for list items. A "key" is a special string attribute you need to include when creating lists of elements. We'll discuss why it's important in the next section.
@@ -86,12 +81,6 @@ function NumberList(props) {
<ul>{listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/jrXYRR?editors=0011)
@@ -165,12 +154,6 @@ function NumberList(props) {
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
```

**Example: Correct Key Usage**
@@ -193,12 +176,6 @@ function NumberList(props) {
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/ZXeOGM?editors=0010)
@@ -239,10 +216,9 @@ const posts = [
{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
{id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
ReactDOM.render(
<Blog posts={posts} />,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Blog posts={posts} />);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/NRZYGN?editors=0010)
3 changes: 2 additions & 1 deletion content/docs/portals.md
Original file line number Diff line number Diff line change
@@ -146,7 +146,8 @@ function Child() {
);
}
ReactDOM.render(<Parent />, appRoot);
const root = ReactDOM.createRoot(appRoot);
root.render(<Parent />);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/jGBWpE)
6 changes: 2 additions & 4 deletions content/docs/react-without-es6.md
Original file line number Diff line number Diff line change
@@ -216,10 +216,8 @@ var TickTock = createReactClass({
}
});

ReactDOM.render(
<TickTock />,
document.getElementById('example')
);
const root = ReactDOM.createRoot(document.getElementById('example'));
root.render(<TickTock />);
```

If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.
18 changes: 6 additions & 12 deletions content/docs/react-without-jsx.md
Original file line number Diff line number Diff line change
@@ -17,10 +17,8 @@ class Hello extends React.Component {
}
}

ReactDOM.render(
<Hello toWhat="World" />,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Hello toWhat="World" />);
```

can be compiled to this code that does not use JSX:
@@ -32,10 +30,8 @@ class Hello extends React.Component {
}
}

ReactDOM.render(
React.createElement(Hello, {toWhat: 'World'}, null),
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(React.createElement(Hello, {toWhat: 'World'}, null));
```

If you're curious to see more examples of how JSX is converted to JavaScript, you can try out [the online Babel compiler](babel://jsx-simple-example).
@@ -47,10 +43,8 @@ If you get tired of typing `React.createElement` so much, one common pattern is
```js
const e = React.createElement;

ReactDOM.render(
e('div', null, 'Hello World'),
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(e('div', null, 'Hello World'));
```

If you use this shorthand form for `React.createElement`, it can be almost as convenient to use React without JSX.
10 changes: 3 additions & 7 deletions content/docs/reference-glossary.md
Original file line number Diff line number Diff line change
@@ -39,13 +39,9 @@ JSX is a syntax extension to JavaScript. It is similar to a template language, b

React DOM uses camelCase property naming convention instead of HTML attribute names. For example, `tabindex` becomes `tabIndex` in JSX. The attribute `class` is also written as `className` since `class` is a reserved word in JavaScript:

```js
const name = 'Clementine';
ReactDOM.render(
<h1 className="hello">My name is {name}!</h1>,
document.getElementById('root')
);
```
```jsx
<h1 className="hello">My name is Clementine!</h1>
```

## [Elements](/docs/rendering-elements.html) {#elements}

8 changes: 3 additions & 5 deletions content/docs/reference-javascript-environment-requirements.md
Original file line number Diff line number Diff line change
@@ -15,12 +15,10 @@ import 'core-js/es/map';
import 'core-js/es/set';

import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOM from 'react-dom/client';

ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<h1>Hello, world!</h1>);
```

React also depends on `requestAnimationFrame` (even in test environments).
8 changes: 4 additions & 4 deletions content/docs/rendering-elements.md
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ We call this a "root" DOM node because everything inside it will be managed by R

Applications built with just React usually have a single root DOM node. If you are integrating React into an existing app, you may have as many isolated root DOM nodes as you like.

To render a React element into a root DOM node, pass both to [`ReactDOM.render()`](/docs/react-dom.html#render):
To render a React element, first pass the DOM element to [`ReactDOM.createRoot()`](/docs/react-dom-client.html#createroot), then pass the React element to `root.render()`:

`embed:rendering-elements/render-an-element.js`

@@ -46,19 +46,19 @@ It displays "Hello, world" on the page.

React elements are [immutable](https://en.wikipedia.org/wiki/Immutable_object). Once you create an element, you can't change its children or attributes. An element is like a single frame in a movie: it represents the UI at a certain point in time.

With our knowledge so far, the only way to update the UI is to create a new element, and pass it to [`ReactDOM.render()`](/docs/react-dom.html#render).
With our knowledge so far, the only way to update the UI is to create a new element, and pass it to `root.render()`.

Consider this ticking clock example:

`embed:rendering-elements/update-rendered-element.js`

**[Try it on CodePen](https://codepen.io/gaearon/pen/gwoJZk?editors=1010)**

It calls [`ReactDOM.render()`](/docs/react-dom.html#render) every second from a [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval) callback.
It calls [`root.render()`](/docs/react-dom.html#render) every second from a [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval) callback.

>**Note:**
>
>In practice, most React apps only call [`ReactDOM.render()`](/docs/react-dom.html#render) once. In the next sections we will learn how such code gets encapsulated into [stateful components](/docs/state-and-lifecycle.html).
>In practice, most React apps only call `root.render()` once. In the next sections we will learn how such code gets encapsulated into [stateful components](/docs/state-and-lifecycle.html).
>
>We recommend that you don't skip topics because they build on each other.
49 changes: 16 additions & 33 deletions content/docs/state-and-lifecycle.md
Original file line number Diff line number Diff line change
@@ -10,20 +10,19 @@ next: handling-events.html

This page introduces the concept of state and lifecycle in a React component. You can find a [detailed component API reference here](/docs/react-component.html).

Consider the ticking clock example from [one of the previous sections](/docs/rendering-elements.html#updating-the-rendered-element). In [Rendering Elements](/docs/rendering-elements.html#rendering-an-element-into-the-dom), we have only learned one way to update the UI. We call `ReactDOM.render()` to change the rendered output:
Consider the ticking clock example from [one of the previous sections](/docs/rendering-elements.html#updating-the-rendered-element). In [Rendering Elements](/docs/rendering-elements.html#rendering-an-element-into-the-dom), we have only learned one way to update the UI. We call `root.render()` to change the rendered output:

```js{8-11}
```js{10}
const root = ReactDOM.createRoot(document.getElementById('root'));
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(
element,
document.getElementById('root')
);
root.render(element);
}
setInterval(tick, 1000);
@@ -35,7 +34,9 @@ In this section, we will learn how to make the `Clock` component truly reusable

We can start by encapsulating how the clock looks:

```js{3-6,12}
```js{5-8,13}
const root = ReactDOM.createRoot(document.getElementById('root'));
function Clock(props) {
return (
<div>
@@ -46,10 +47,7 @@ function Clock(props) {
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
root.render(<Clock date={new Date()} />);
}
setInterval(tick, 1000);
@@ -62,10 +60,7 @@ However, it misses a crucial requirement: the fact that the `Clock` sets up a ti
Ideally we want to write this once and have the `Clock` update itself:

```js{2}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
root.render(<Clock />);
```

To implement this, we need to add "state" to the `Clock` component.
@@ -158,10 +153,7 @@ Class components should always call the base constructor with `props`.
3) Remove the `date` prop from the `<Clock />` element:

```js{2}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
root.render(<Clock />);
```

We will later add the timer code back to the component itself.
@@ -185,10 +177,8 @@ class Clock extends React.Component {
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/KgQpJd?editors=0010)
@@ -294,10 +284,8 @@ class Clock extends React.Component {
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/amqdNA?editors=0010)
@@ -306,7 +294,7 @@ Now the clock ticks every second.

Let's quickly recap what's going on and the order in which the methods are called:

1) When `<Clock />` is passed to `ReactDOM.render()`, React calls the constructor of the `Clock` component. Since `Clock` needs to display the current time, it initializes `this.state` with an object including the current time. We will later update this state.
1) When `<Clock />` is passed to `root.render()`, React calls the constructor of the `Clock` component. Since `Clock` needs to display the current time, it initializes `this.state` with an object including the current time. We will later update this state.

2) React then calls the `Clock` component's `render()` method. This is how React learns what should be displayed on the screen. React then updates the DOM to match the `Clock`'s render output.

@@ -447,11 +435,6 @@ function App() {
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/vXdGmd?editors=0010)
2 changes: 1 addition & 1 deletion content/docs/testing-recipes.md
Original file line number Diff line number Diff line change
@@ -605,7 +605,7 @@ It's typically better to make more specific assertions than to use snapshots. Th

### Multiple Renderers {#multiple-renderers}

In rare cases, you may be running a test on a component that uses multiple renderers. For example, you may be running snapshot tests on a component with `react-test-renderer`, that internally uses `ReactDOM.render` inside a child component to render some content. In this scenario, you can wrap updates with `act()`s corresponding to their renderers.
In rare cases, you may be running a test on a component that uses multiple renderers. For example, you may be running snapshot tests on a component with `react-test-renderer`, that internally uses `render` from `react-dom` inside a child component to render some content. In this scenario, you can wrap updates with `act()`s corresponding to their renderers.

```jsx
import { act as domAct } from "react-dom/test-utils";
2 changes: 1 addition & 1 deletion content/docs/thinking-in-react.md
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@ To build a static version of your app that renders your data model, you'll want

You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with `FilterableProductTable`) or with the ones lower in it (`ProductRow`). In simpler examples, it's usually easier to go top-down, and on larger projects, it's easier to go bottom-up and write tests as you build.

At the end of this step, you'll have a library of reusable components that render your data model. The components will only have `render()` methods since this is a static version of your app. The component at the top of the hierarchy (`FilterableProductTable`) will take your data model as a prop. If you make a change to your underlying data model and call `ReactDOM.render()` again, the UI will be updated. You can see how your UI is updated and where to make changes. React's **one-way data flow** (also called *one-way binding*) keeps everything modular and fast.
At the end of this step, you'll have a library of reusable components that render your data model. The components will only have `render()` methods since this is a static version of your app. The component at the top of the hierarchy (`FilterableProductTable`) will take your data model as a prop. If you make a change to your underlying data model and call `root.render()` again, the UI will be updated. You can see how your UI is updated and where to make changes. React's **one-way data flow** (also called *one-way binding*) keeps everything modular and fast.

Refer to the [React docs](/docs/getting-started.html) if you need help executing this step.

6 changes: 2 additions & 4 deletions content/docs/typechecking-with-proptypes.md
Original file line number Diff line number Diff line change
@@ -173,10 +173,8 @@ Greeting.defaultProps = {
};

// Renders "Hello, Stranger":
ReactDOM.render(
<Greeting />,
document.getElementById('example')
);
const root = ReactDOM.createRoot(document.getElementById('example'));
root.render(<Greeting />);
```

If you are using a Babel transform like [plugin-proposal-class-properties](https://babeljs.io/docs/en/babel-plugin-proposal-class-properties/) (previously _plugin-transform-class-properties_), you can also declare `defaultProps` as static property within a React component class. This syntax has not yet been finalized though and will require a compilation step to work within a browser. For more information, see the [class fields proposal](https://github.com/tc39/proposal-class-fields).
3 changes: 2 additions & 1 deletion content/docs/web-components.md
Original file line number Diff line number Diff line change
@@ -50,7 +50,8 @@ class XSearch extends HTMLElement {

const name = this.getAttribute('name');
const url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
ReactDOM.render(<a href={url}>{name}</a>, mountPoint);
const root = ReactDOM.createRoot(mountPoint);
root.render(<a href={url}>{name}</a>);
}
}
customElements.define('x-search', XSearch);
5 changes: 4 additions & 1 deletion examples/rendering-elements/render-an-element.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
const root = ReactDOM.createRoot(
document.getElementById('root')
);
root.render(element);
6 changes: 5 additions & 1 deletion examples/rendering-elements/update-rendered-element.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
const root = ReactDOM.createRoot(
document.getElementById('root')
);

function tick() {
const element = (
<div>
@@ -6,7 +10,7 @@ function tick() {
</div>
);
// highlight-next-line
ReactDOM.render(element, document.getElementById('root'));
root.render(element);
}

setInterval(tick, 1000);