Skip to content

Commit 62cc6b1

Browse files
merging all conflicts
2 parents 9bde861 + 47e64bf commit 62cc6b1

2 files changed

Lines changed: 265 additions & 10 deletions

File tree

src/content/learn/react-compiler/installation.md

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,36 @@ module.exports = {
6464

6565
### Vite {/*vite*/}
6666

67+
<<<<<<< HEAD
6768
Vite를 사용하는 경우 `vite-plugin-react`에 플러그인을 추가할 수 있습니다.
69+
=======
70+
If you use Vite with version 6.0.0 or later of `@vitejs/plugin-react`, you can use the `reactCompilerPreset`:
71+
>>>>>>> 47e64bf7ad81aab8bacfa791a37816ee869135eb
6872
69-
```js {3,9}
73+
<TerminalBlock>
74+
npm install -D @rolldown/plugin-babel
75+
</TerminalBlock>
76+
77+
```js {3-4,9-11}
78+
// vite.config.js
79+
import { defineConfig } from 'vite';
80+
import react, { reactCompilerPreset } from '@vitejs/plugin-react';
81+
import babel from '@rolldown/plugin-babel';
82+
83+
export default defineConfig({
84+
plugins: [
85+
react(),
86+
babel({
87+
presets: [reactCompilerPreset()]
88+
}),
89+
],
90+
});
91+
```
92+
93+
<Note>
94+
In `@vitejs/plugin-react@6.0.0`, the inline Babel option was removed. If you're using an older version, you can use:
95+
96+
```js
7097
// vite.config.js
7198
import { defineConfig } from 'vite';
7299
import react from '@vitejs/plugin-react';
@@ -81,26 +108,25 @@ export default defineConfig({
81108
],
82109
});
83110
```
111+
</Note>
84112

113+
<<<<<<< HEAD
85114
또는 Vite용 별도의 Babel 플러그인을 선호하는 경우
115+
=======
116+
Alternatively, you can use the Babel plugin directly with `@rolldown/plugin-babel`:
117+
>>>>>>> 47e64bf7ad81aab8bacfa791a37816ee869135eb
86118
87-
<TerminalBlock>
88-
npm install -D vite-plugin-babel
89-
</TerminalBlock>
90-
91-
```js {2,11}
119+
```js {3,9}
92120
// vite.config.js
93-
import babel from 'vite-plugin-babel';
94121
import { defineConfig } from 'vite';
95122
import react from '@vitejs/plugin-react';
123+
import babel from '@rolldown/plugin-babel';
96124

97125
export default defineConfig({
98126
plugins: [
99127
react(),
100128
babel({
101-
babelConfig: {
102-
plugins: ['babel-plugin-react-compiler'],
103-
},
129+
plugins: ['babel-plugin-react-compiler'],
104130
}),
105131
],
106132
});

src/content/reference/react/useOptimistic.md

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,236 @@ function MyComponent({name, todos}) {
5555
5656
`useOptimistic` Hook은 네트워크 요청과 같은 백그라운드 작업이 완료되기 전에 사용자 인터페이스를 낙관적으로 업데이트하는 방법을 제공합니다. 폼의 맥락에서, 이 기술은 앱이 더 반응적으로 느껴지도록 도와줍니다. 사용자가 폼을 제출할 때, 서버의 응답을 기다리는 대신 인터페이스는 기대하는 결과로 즉시 업데이트됩니다.
5757
58+
<<<<<<< HEAD
5859
예를 들어, 사용자가 폼에 메시지를 입력하고 "전송" 버튼을 누르면, `useOptimistic` Hook은 메시지가 실제로 서버로 전송되기 전에 "전송 중..." 라벨이 있는 목록에 메시지가 즉시 나타나도록 합니다. 이 "낙관적" 접근법은 속도와 반응성의 느낌을 줍니다. 그런 다음 폼은 백그라운드에서 메시지를 실제로 전송하려고 시도합니다. 서버가 메시지를 받았음을 확인하면, "전송 중..." 라벨이 제거됩니다.
60+
=======
61+
function handleClick() {
62+
startTransition(async () => {
63+
setOptimisticLike(true);
64+
setOptimisticSubs(a => a + 1);
65+
await saveChanges();
66+
});
67+
}
68+
```
69+
70+
#### Parameters {/*setoptimistic-parameters*/}
71+
72+
* `optimisticState`: The value that you want the optimistic state to be during an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). If you provided a `reducer` to `useOptimistic`, this value will be passed as the second argument to your reducer. It can be a value of any type.
73+
* If you pass a function as `optimisticState`, it will be treated as an _updater function_. It must be pure, should take the pending state as its only argument, and should return the next optimistic state. React will put your updater function in a queue and re-render your component. During the next render, React will calculate the next state by applying the queued updaters to the previous state similar to [`useState` updaters](/reference/react/useState#setstate-parameters).
74+
75+
#### Returns {/*setoptimistic-returns*/}
76+
77+
`set` functions do not have a return value.
78+
79+
#### Caveats {/*setoptimistic-caveats*/}
80+
81+
* The `set` function must be called inside an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). If you call the setter outside an Action, [React will show a warning](#an-optimistic-state-update-occurred-outside-a-transition-or-action) and the optimistic state will briefly render.
82+
83+
<DeepDive>
84+
85+
#### How optimistic state works {/*how-optimistic-state-works*/}
86+
87+
`useOptimistic` lets you show a temporary value while an Action is in progress:
88+
89+
```js
90+
const [value, setValue] = useState('a');
91+
const [optimistic, setOptimistic] = useOptimistic(value);
92+
93+
startTransition(async () => {
94+
setOptimistic('b');
95+
const newValue = await saveChanges('b');
96+
setValue(newValue);
97+
});
98+
```
99+
100+
When the setter is called inside an Action, `useOptimistic` will trigger a re-render to show that state while the Action is in progress. Otherwise, the `value` passed to `useOptimistic` is returned.
101+
102+
This state is called the "optimistic" because it is used to immediately present the user with the result of performing an Action, even though the Action actually takes time to complete.
103+
104+
**How the update flows**
105+
106+
1. **Update immediately**: When `setOptimistic('b')` is called, React immediately renders with `'b'`.
107+
108+
2. **(Optional) await in Action**: If you await in the Action, React continues showing `'b'`.
109+
110+
3. **Transition scheduled**: `setValue(newValue)` schedules an update to the real state.
111+
112+
4. **(Optional) wait for Suspense**: If `newValue` suspends, React continues showing `'b'`.
113+
114+
5. **Single render commit**: Finally, the `newValue` commits for `value` and `optimistic`.
115+
116+
There's no extra render to "clear" the optimistic state. The optimistic and real state converge in the same render when the Transition completes.
117+
118+
<Note>
119+
120+
#### Optimistic state is temporary {/*optimistic-state-is-temporary*/}
121+
122+
Optimistic state only renders while an Action is in progress, otherwise `value` is rendered.
123+
124+
If `saveChanges` returned `'c'`, then both `value` and `optimistic` will be `'c'`, not `'b'`.
125+
126+
</Note>
127+
128+
**How the final state is determined**
129+
130+
The `value` argument to `useOptimistic` determines what displays after the Action finishes. How this works depends on the pattern you use:
131+
132+
- **Hardcoded values** like `useOptimistic(false)`: After the Action, `state` is still `false`, so the UI shows `false`. This is useful for pending states where you always start from `false`.
133+
134+
- **Props or state passed in** like `useOptimistic(isLiked)`: If the parent updates `isLiked` during the Action, the new value is used after the Action completes. This is how the UI reflects the result of the Action.
135+
136+
- **Reducer pattern** like `useOptimistic(items, fn)`: If `items` changes while the Action is pending, React re-runs your `reducer` with the new `items` to recalculate the state. This keeps your optimistic additions on top of the latest data.
137+
138+
**What happens when the Action fails**
139+
140+
If the Action throws an error, the Transition still ends, and React renders with whatever `value` currently is. Since the parent typically only updates `value` on success, a failure means `value` hasn't changed, so the UI shows what it showed before the optimistic update. You can catch the error to show a message to the user.
141+
142+
</DeepDive>
143+
144+
---
145+
146+
## Usage {/*usage*/}
147+
148+
### Adding optimistic state to a component {/*adding-optimistic-state-to-a-component*/}
149+
150+
Call `useOptimistic` at the top level of your component to declare one or more optimistic states.
151+
152+
```js [[1, 4, "age"], [1, 5, "name"], [1, 6, "todos"], [2, 4, "optimisticAge"], [2, 5, "optimisticName"], [2, 6, "optimisticTodos"], [3, 4, "setOptimisticAge"], [3, 5, "setOptimisticName"], [3, 6, "setOptimisticTodos"], [4, 6, "reducer"]]
153+
import { useOptimistic } from 'react';
154+
155+
function MyComponent({age, name, todos}) {
156+
const [optimisticAge, setOptimisticAge] = useOptimistic(age);
157+
const [optimisticName, setOptimisticName] = useOptimistic(name);
158+
const [optimisticTodos, setOptimisticTodos] = useOptimistic(todos, reducer);
159+
// ...
160+
```
161+
162+
`useOptimistic` returns an array with exactly two items:
163+
164+
1. The <CodeStep step={2}>optimistic state</CodeStep>, initially set to the <CodeStep step={1}>value</CodeStep> provided.
165+
2. The <CodeStep step={3}>set function</CodeStep> that lets you temporarily change the state during an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions).
166+
* If a <CodeStep step={4}>reducer</CodeStep> is provided, it will run before returning the optimistic state.
167+
168+
To use the <CodeStep step={2}>optimistic state</CodeStep>, call the `set` function inside an Action.
169+
170+
Actions are functions called inside `startTransition`:
171+
172+
```js {3}
173+
function onAgeChange(e) {
174+
startTransition(async () => {
175+
setOptimisticAge(42);
176+
const newAge = await postAge(42);
177+
setAge(newAge);
178+
});
179+
}
180+
```
181+
182+
React will render the optimistic state `42` first while the `age` remains the current age. The Action waits for POST, and then renders the `newAge` for both `age` and `optimisticAge`.
183+
184+
See [How optimistic state works](#how-optimistic-state-works) for a deep dive.
185+
186+
<Note>
187+
188+
When using [Action props](/reference/react/useTransition#exposing-action-props-from-components), you can call the set function without `startTransition`:
189+
190+
```js [[3, 2, "setOptimisticName"]]
191+
async function submitAction() {
192+
setOptimisticName('Taylor');
193+
await updateName('Taylor');
194+
}
195+
```
196+
197+
This works because Action props are already called inside `startTransition`.
198+
199+
For an example, see: [Using optimistic state in Action props](#using-optimistic-state-in-action-props).
200+
201+
</Note>
202+
203+
---
204+
205+
### Using optimistic state in Action props {/*using-optimistic-state-in-action-props*/}
206+
207+
In an [Action prop](/reference/react/useTransition#exposing-action-props-from-components), you can call the optimistic setter directly without `startTransition`.
208+
209+
This example sets optimistic state inside a `<form>` `submitAction` prop:
210+
211+
<Sandpack>
212+
213+
```js src/App.js
214+
import { useState, startTransition } from 'react';
215+
import EditName from './EditName';
216+
217+
export default function App() {
218+
const [name, setName] = useState('Alice');
219+
220+
return <EditName name={name} action={setName} />;
221+
}
222+
```
223+
224+
```js src/EditName.js active
225+
import { useOptimistic, startTransition } from 'react';
226+
import { updateName } from './actions.js';
227+
228+
export default function EditName({ name, action }) {
229+
const [optimisticName, setOptimisticName] = useOptimistic(name);
230+
231+
async function submitAction(formData) {
232+
const newName = formData.get('name');
233+
setOptimisticName(newName);
234+
235+
const updatedName = await updateName(newName);
236+
startTransition(() => {
237+
action(updatedName);
238+
})
239+
}
240+
241+
return (
242+
<form action={submitAction}>
243+
<p>Your name is: {optimisticName}</p>
244+
<p>
245+
<label>Change it: </label>
246+
<input
247+
type="text"
248+
name="name"
249+
disabled={name !== optimisticName}
250+
/>
251+
</p>
252+
</form>
253+
);
254+
}
255+
```
256+
257+
```js src/actions.js hidden
258+
export async function updateName(name) {
259+
await new Promise((res) => setTimeout(res, 1000));
260+
return name;
261+
}
262+
```
263+
264+
</Sandpack>
265+
266+
In this example, when the user submits the form, the `optimisticName` updates immediately to show the `newName` optimistically while the server request is in progress. When the request completes, `name` and `optimisticName` are rendered with the actual `updatedName` from the response.
267+
268+
<DeepDive>
269+
270+
#### Why doesn't this need `startTransition`? {/*why-doesnt-this-need-starttransition*/}
271+
272+
By convention, props called inside `startTransition` are named with "Action".
273+
274+
Since `submitAction` is named with "Action", you know it's already called inside `startTransition`.
275+
276+
See [Exposing `action` prop from components](/reference/react/useTransition#exposing-action-props-from-components) for the Action prop pattern.
277+
278+
</DeepDive>
279+
280+
---
281+
282+
### Adding optimistic state to Action props {/*adding-optimistic-state-to-action-props*/}
283+
284+
When creating an [Action prop](/reference/react/useTransition#exposing-action-props-from-components), you can add `useOptimistic` to show immediate feedback.
285+
286+
Here's a button that shows "Submitting..." while the `action` is pending:
287+
>>>>>>> 47e64bf7ad81aab8bacfa791a37816ee869135eb
59288
60289
<Sandpack>
61290

0 commit comments

Comments
 (0)