Skip to content
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

Sync with react.dev @ b12743c3 #775

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
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
28 changes: 28 additions & 0 deletions src/content/blog/2024/04/25/react-19-upgrade-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,11 @@

<Note>

<<<<<<< HEAD
codemod で以下のように `ReactDOM.render` を `ReactDOM.createRoot` に変換できます。
=======
Codemod `ReactDOM.render` to `ReactDOMClient.createRoot`:
>>>>>>> b12743c31af7f5cda2c25534f64281ff030b7205

```bash
npx codemod@latest react/19/replace-reactdom-render
Expand All @@ -427,6 +431,15 @@
hydrateRoot(document.getElementById('root'), <App />);
```

<Note>

Codemod `ReactDOM.hydrate` to `ReactDOMClient.hydrateRoot`:

```bash
npx codemod@latest react/19/replace-reactdom-render
```

</Note>

#### 削除:`unmountComponentAtNode` {/*removed-unmountcomponentatnode*/}

Expand All @@ -443,9 +456,24 @@

詳細については、[`createRoot`](https://react.dev/reference/react-dom/client/createRoot#root-unmount) と [`hydrateRoot`](https://react.dev/reference/react-dom/client/hydrateRoot#root-unmount) の `root.unmount()` をご覧ください。

<Note>

Codemod `unmountComponentAtNode` to `root.unmount`:

```bash
npx codemod@latest react/19/replace-reactdom-render
```

</Note>

<<<<<<< HEAD

Check failure on line 469 in src/content/blog/2024/04/25/react-19-upgrade-guide.md

View workflow job for this annotation

GitHub Actions / Lint on node 20.x and ubuntu-latest

コンフリクトマーカーが残っています。コンフリクトを解消してください。
#### 削除:`ReactDOM.findDOMNode` {/*removed-reactdom-finddomnode*/}
`ReactDOM.findDOMNode` は [2018 年 10 月 (v16.6.0)](https://legacy.reactjs.org/blog/2018/10/23/react-v-16-6.html#deprecations-in-strictmode) に非推奨化されました。
=======
#### Removed: `ReactDOM.findDOMNode` {/*removed-reactdom-finddomnode*/}

`ReactDOM.findDOMNode` was [deprecated in October 2018 (v16.6.0)](https://legacy.reactjs.org/blog/2018/10/23/react-v-16-6.html#deprecations-in-strictmode).
>>>>>>> b12743c31af7f5cda2c25534f64281ff030b7205

`findDOMNode` はレガシーな避難ハッチであり、実行速度が遅く、リファクタリングが困難で、最初の子要素しか返せず、抽象化レイヤーを破壊するといった問題があるため(詳細は[こちら](https://legacy.reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage))、削除されます。`ReactDOM.findDOMNode` は [DOM 用の ref](/learn/manipulating-the-dom-with-refs) で置き換えることができます。

Expand Down
177 changes: 177 additions & 0 deletions src/content/reference/react/act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
---
title: act
---

<Intro>

`act` is a test helper to apply pending React updates before making assertions.

```js
await act(async actFn)
```

</Intro>

To prepare a component for assertions, wrap the code rendering it and performing updates inside an `await act()` call. This makes your test run closer to how React works in the browser.

<Note>
You might find using `act()` directly a bit too verbose. To avoid some of the boilerplate, you could use a library like [React Testing Library](https://testing-library.com/docs/react-testing-library/intro), whose helpers are wrapped with `act()`.
</Note>


<InlineToc />

---

## Reference {/*reference*/}

### `await act(async actFn)` {/*await-act-async-actfn*/}

When writing UI tests, tasks like rendering, user events, or data fetching can be considered as “units” of interaction with a user interface. React provides a helper called `act()` that makes sure all updates related to these “units” have been processed and applied to the DOM before you make any assertions.

The name `act` comes from the [Arrange-Act-Assert](https://wiki.c2.com/?ArrangeActAssert) pattern.

```js {2,4}
it ('renders with button disabled', async () => {
await act(async () => {
root.render(<TestComponent />)
});
expect(container.querySelector('button')).toBeDisabled();
});
```

<Note>

We recommend using `act` with `await` and an `async` function. Although the sync version works in many cases, it doesn't work in all cases and due to the way React schedules updates internally, it's difficult to predict when you can use the sync version.

We will deprecate and remove the sync version in the future.

</Note>

#### Parameters {/*parameters*/}

* `async actFn`: An async function wrapping renders or interactions for components being tested. Any updates triggered within the `actFn`, are added to an internal act queue, which are then flushed together to process and apply any changes to the DOM. Since it is async, React will also run any code that crosses an async boundary, and flush any updates scheduled.

#### Returns {/*returns*/}

`act` does not return anything.

## Usage {/*usage*/}

When testing a component, you can use `act` to make assertions about its output.

For example, let’s say we have this `Counter` component, the usage examples below show how to test it:

```js
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(prev => prev + 1);
}

useEffect(() => {
document.title = `You clicked ${this.state.count} times`;
}, [count]);

return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
)
}
```

### Rendering components in tests {/*rendering-components-in-tests*/}

To test the render output of a component, wrap the render inside `act()`:

```js {10,12}
import {act} from 'react';
import ReactDOM from 'react-dom/client';
import Counter from './Counter';

it('can render and update a counter', async () => {
container = document.createElement('div');
document.body.appendChild(container);

// ✅ Render the component inside act().
await act(() => {
ReactDOM.createRoot(container).render(<Counter />);
});

const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('You clicked 0 times');
expect(document.title).toBe('You clicked 0 times');
});
```

Here, wwe create a container, append it to the document, and render the `Counter` component inside `act()`. This ensures that the component is rendered and its effects are applied before making assertions.

Using `act` ensures that all updates have been applied before we make assertions.

### Dispatching events in tests {/*dispatching-events-in-tests*/}

To test events, wrap the event dispatch inside `act()`:

```js {14,16}
import {act} from 'react';
import ReactDOM from 'react-dom/client';
import Counter from './Counter';

it.only('can render and update a counter', async () => {
const container = document.createElement('div');
document.body.appendChild(container);

await act( async () => {
ReactDOMClient.createRoot(container).render(<Counter />);
});

// ✅ Dispatch the event inside act().
await act(async () => {
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});

const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('You clicked 1 times');
expect(document.title).toBe('You clicked 1 times');
});
```

Here, we render the component with `act`, and then dispatch the event inside another `act()`. This ensures that all updates from the event are applied before making assertions.

<Pitfall>

Don’t forget that dispatching DOM events only works when the DOM container is added to the document. You can use a library like [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) to reduce the boilerplate code.

</Pitfall>

## Troubleshooting {/*troubleshooting*/}

### I'm getting an error: "The current testing environment is not configured to support act"(...)" {/*error-the-current-testing-environment-is-not-configured-to-support-act*/}

Using `act` requires setting `global.IS_REACT_ACT_ENVIRONMENT=true` in your test environment. This is to ensure that `act` is only used in the correct environment.

If you don't set the global, you will see an error like this:

<ConsoleBlock level="error">

Warning: The current testing environment is not configured to support act(...)

</ConsoleBlock>

To fix, add this to your global setup file for React tests:

```js
global.IS_REACT_ACT_ENVIRONMENT=true
```

<Note>

In testing frameworks like [React Testing Library](https://testing-library.com/docs/react-testing-library/intro), `IS_REACT_ACT_ENVIRONMENT` is already set for you.

</Note>
9 changes: 9 additions & 0 deletions src/content/reference/react/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,20 @@

---

<<<<<<< HEAD

Check failure on line 13 in src/content/reference/react/apis.md

View workflow job for this annotation

GitHub Actions / Lint on node 20.x and ubuntu-latest

コンフリクトマーカーが残っています。コンフリクトを解消してください。
* [`createContext`](/reference/react/createContext) を利用すると、子コンポーネントに対してコンテクストを定義および提供できます。[`useContext`](/reference/react/useContext) と一緒に使用されます。
* [`forwardRef`](/reference/react/forwardRef) を利用すると、コンポーネントの DOM ノードを ref として親に公開できます。[`useRef`](/reference/react/useRef) と一緒に使用されます。
* [`lazy`](/reference/react/lazy) を利用すると、コンポーネントのコードの読み込みを初回レンダーまで遅延することができます。
* [`memo`](/reference/react/memo) を利用すると、同じ props を持つコンポーネントの再レンダーをスキップできます。[`useMemo`](/reference/react/useMemo) や [`useCallback`](/reference/react/useCallback) と一緒に使用されます。
* [`startTransition`](/reference/react/startTransition) を使うと、state の更新を低緊急度 (non-urgent) としてマークできます。[`useTransition`](/reference/react/useTransition) に似ています。
=======
* [`createContext`](/reference/react/createContext) lets you define and provide context to the child components. Used with [`useContext`.](/reference/react/useContext)
* [`forwardRef`](/reference/react/forwardRef) lets your component expose a DOM node as a ref to the parent. Used with [`useRef`.](/reference/react/useRef)
* [`lazy`](/reference/react/lazy) lets you defer loading a component's code until it's rendered for the first time.
* [`memo`](/reference/react/memo) lets your component skip re-renders with same props. Used with [`useMemo`](/reference/react/useMemo) and [`useCallback`.](/reference/react/useCallback)
* [`startTransition`](/reference/react/startTransition) lets you mark a state update as non-urgent. Similar to [`useTransition`.](/reference/react/useTransition)
* [`act`](/reference/react/act) lets you wrap renders and interactions in tests to ensure updates have processed before making assertions.
>>>>>>> b12743c31af7f5cda2c25534f64281ff030b7205

---

Expand Down
2 changes: 1 addition & 1 deletion src/content/warnings/react-test-renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ title: react-test-renderer Deprecation Warnings

react-test-renderer is deprecated. A warning will fire whenever calling ReactTestRenderer.create() or ReactShallowRender.render(). The react-test-renderer package will remain available on NPM but will not be maintained and may break with new React features or changes to React's internals.

The React Team recommends migrating your tests to [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) or [@testing-library/react-native](https://callstack.github.io/react-native-testing-library/docs/getting-started) for a modern and well supported testing experience.
The React Team recommends migrating your tests to [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) or [@testing-library/react-native](https://callstack.github.io/react-native-testing-library/docs/start/intro) for a modern and well supported testing experience.


## new ShallowRenderer() warning {/*new-shallowrenderer-warning*/}
Expand Down
11 changes: 10 additions & 1 deletion src/sidebarReference.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@
"title": "API",
"path": "/reference/react/apis",
"routes": [
{
"title": "act",
"path": "/reference/react/act"
},
{
"title": "cache",
"path": "/reference/react/cache",
Expand Down Expand Up @@ -342,8 +346,13 @@
"path": "/reference/rules",
"routes": [
{
<<<<<<< HEAD
"title": "コンポーネントとフックを純粋に保つ",
"path": "/reference/rules/components-and-hooks-must-be-pure"
=======
"title": "Components and Hooks must be pure",
"path": "/reference/rules/components-and-hooks-must-be-pure"
>>>>>>> b12743c31af7f5cda2c25534f64281ff030b7205
},
{
"title": "コンポーネントやフックを呼び出すのは React",
Expand Down Expand Up @@ -429,4 +438,4 @@
]
}
]
}
}
Loading