diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml
index af0a1497d..8330e30d2 100644
--- a/.github/workflows/analyze.yml
+++ b/.github/workflows/analyze.yml
@@ -11,10 +11,10 @@ jobs:
analyze:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up node
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v3
with:
node-version: '20.x'
@@ -22,7 +22,7 @@ jobs:
uses: bahmutov/npm-install@v1.7.10
- name: Restore next build
- uses: actions/cache@v2
+ uses: actions/cache@v3
id: restore-build-cache
env:
cache-name: cache-next-build
diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md
index 58e8a3ddf..89b6240b3 100644
--- a/src/content/reference/react/useCallback.md
+++ b/src/content/reference/react/useCallback.md
@@ -709,7 +709,7 @@ function ChatRoom({ roomId }) {
useEffect(() => {
const options = createOptions();
- const connection = createConnection();
+ const connection = createConnection(options);
connection.connect();
// ...
```
@@ -720,7 +720,7 @@ function ChatRoom({ roomId }) {
```js {6}
useEffect(() => {
const options = createOptions();
- const connection = createConnection();
+ const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [createOptions]); // ๐ด ๋ฌธ์ ์ : ์ด ์์กด์ฑ์ ๋งค ๋ ๋๋ง๋ง๋ค ๋ณ๊ฒฝ๋ฉ๋๋ค.
@@ -742,7 +742,7 @@ function ChatRoom({ roomId }) {
useEffect(() => {
const options = createOptions();
- const connection = createConnection();
+ const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [createOptions]); // โ
createOptions๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ๋ณ๊ฒฝ๋ฉ๋๋ค.
@@ -764,7 +764,7 @@ function ChatRoom({ roomId }) {
}
const options = createOptions();
- const connection = createConnection();
+ const connection = createConnection(options);
connection.connect();
return () => connection.disconnect();
}, [roomId]); // โ
roomId๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ๋ณ๊ฒฝ๋ฉ๋๋ค.
diff --git a/src/content/reference/react/useMemo.md b/src/content/reference/react/useMemo.md
index 57baf01d7..9b4be3e84 100644
--- a/src/content/reference/react/useMemo.md
+++ b/src/content/reference/react/useMemo.md
@@ -1056,6 +1056,82 @@ label {
---
+### Preventing an Effect from firing too often {/*preventing-an-effect-from-firing-too-often*/}
+
+Sometimes, you might want to use a value inside an [Effect:](/learn/synchronizing-with-effects)
+
+```js {4-7,10}
+function ChatRoom({ roomId }) {
+ const [message, setMessage] = useState('');
+
+ const options = {
+ serverUrl: 'https://localhost:1234',
+ roomId: roomId
+ }
+
+ useEffect(() => {
+ const connection = createConnection(options);
+ connection.connect();
+ // ...
+```
+
+This creates a problem. [Every reactive value must be declared as a dependency of your Effect.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) However, if you declare `options` as a dependency, it will cause your Effect to constantly reconnect to the chat room:
+
+
+```js {5}
+ useEffect(() => {
+ const connection = createConnection(options);
+ connection.connect();
+ return () => connection.disconnect();
+ }, [options]); // ๐ด Problem: This dependency changes on every render
+ // ...
+```
+
+To solve this, you can wrap the object you need to call from an Effect in `useMemo`:
+
+```js {4-9,16}
+function ChatRoom({ roomId }) {
+ const [message, setMessage] = useState('');
+
+ const options = useMemo(() => {
+ return {
+ serverUrl: 'https://localhost:1234',
+ roomId: roomId
+ };
+ }, [roomId]); // โ
Only changes when roomId changes
+
+ useEffect(() => {
+ const options = createOptions();
+ const connection = createConnection(options);
+ connection.connect();
+ return () => connection.disconnect();
+ }, [options]); // โ
Only changes when createOptions changes
+ // ...
+```
+
+This ensures that the `options` object is the same between re-renders if `useMemo` returns the cached object.
+
+However, since `useMemo` is performance optimization, not a semantic guarantee, React may throw away the cached value if [there is a specific reason to do that](#caveats). This will also cause the effect to re-fire, **so it's even better to remove the need for a function dependency** by moving your object *inside* the Effect:
+
+```js {5-8,13}
+function ChatRoom({ roomId }) {
+ const [message, setMessage] = useState('');
+
+ useEffect(() => {
+ const options = { // โ
No need for useMemo or object dependencies!
+ serverUrl: 'https://localhost:1234',
+ roomId: roomId
+ }
+
+ const connection = createConnection(options);
+ connection.connect();
+ return () => connection.disconnect();
+ }, [roomId]); // โ
Only changes when roomId changes
+ // ...
+```
+
+Now your code is simpler and doesn't need `useMemo`. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
+
### ๋ค๋ฅธ Hook์ ์ข
์์ฑ ๋ฉ๋ชจํ {/*memoizing-a-dependency-of-another-hook*/}
์ปดํฌ๋ํธ ๋ณธ๋ฌธ์์ ์ง์ ์์ฑ๋ ๊ฐ์ฒด์ ์์กดํ๋ ์ฐ์ฐ์ด ์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
diff --git a/src/content/reference/react/useReducer.md b/src/content/reference/react/useReducer.md
index 08624b1d4..9b45391f2 100644
--- a/src/content/reference/react/useReducer.md
+++ b/src/content/reference/react/useReducer.md
@@ -52,6 +52,7 @@ function MyComponent() {
#### ์ฃผ์ ์ฌํญ {/*caveats*/}
* `useReducer`๋ Hook์ด๋ฏ๋ก **์ปดํฌ๋ํธ์ ์ต์์** ๋๋ ์ปค์คํ
Hook์์๋ง ํธ์ถํ ์ ์์ต๋๋ค. ๋ฐ๋ณต๋ฌธ์ด๋ ์กฐ๊ฑด๋ฌธ์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ํ์ํ ๊ฒฝ์ฐ ์๋ก์ด ์ปดํฌ๋ํธ๋ฅผ ์ถ์ถํ๊ณ ํด๋น ์ปดํฌ๋ํธ๋ก state๋ฅผ ์ฎ๊ฒจ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+* The `dispatch` function has a stable identity, so you will often see it omitted from effect dependencies, but including it will not cause the effect to fire. If the linter lets you omit a dependency without errors, it is safe to do. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
* Strict Mode์์๋ [์ฐ์ฐํ ๋น์์์ฑ](#my-reducer-or-initializer-function-runs-twice)์ ์ฐพ์๋ด๊ธฐ ์ํด reducer์ init ํจ์๋ฅผ ๋๋ฒ ํธ์ถํฉ๋๋ค. ๊ฐ๋ฐ ํ๊ฒฝ์์๋ง ํ์ ๋ ๋์์ด๋ฉฐ, ๋ฐฐํฌ ๋ชจ๋์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค. reducer์ init ํจ์๊ฐ ์์ ํจ์๋ผ๋ฉด(๊ทธ๋์ผ๋ง ํ๋ฏ์ด) ๋ก์ง์ ์ด๋ ํ ์ํฅ๋ ๋ฏธ์น์ง ์์ต๋๋ค. ํธ์ถ ์ค ํ๋์ ๊ฒฐ๊ณผ๋ ๋ฌด์ํฉ๋๋ค.
---
diff --git a/src/content/reference/react/useState.md b/src/content/reference/react/useState.md
index 6db1c06a6..0a3d5676c 100644
--- a/src/content/reference/react/useState.md
+++ b/src/content/reference/react/useState.md
@@ -85,6 +85,8 @@ function handleClick() {
* React๋ [state ์
๋ฐ์ดํธ๋ฅผ batch ํฉ๋๋ค. ](/learn/queueing-a-series-of-state-updates) **๋ชจ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์คํ๋๊ณ ** `set` ํจ์๋ฅผ ํธ์ถํ ํ์ ํ๋ฉด์ ์
๋ฐ์ดํธํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋จ์ผ ์ด๋ฒคํธ ์ค์ ์ฌ๋ฌ ๋ฒ ๋ฆฌ๋ ๋๋ง ํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. ๋๋ฌผ์ง๋ง DOM์ ์ ๊ทผํ๊ธฐ ์ํด React๊ฐ ํ๋ฉด์ ๋ ์ผ์ฐ ์
๋ฐ์ดํธํ๋๋ก ๊ฐ์ ํด์ผ ํ๋ ๊ฒฝ์ฐ, [`flushSync`](/reference/react-dom/flushSync)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
+* The `set` function has a stable identity, so you will often see it omitted from effect dependencies, but including it will not cause the effect to fire. If the linter lets you omit a dependency without errors, it is safe to do. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
+
* *๋ ๋๋ง ๋์ค* `set` ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ ํ์ฌ ๋ ๋๋ง ์ค์ธ ์ปดํฌ๋ํธ ๋ด์์๋ง ํ์ฉ๋ฉ๋๋ค. React๋ ํด๋น ์ถ๋ ฅ์ ๋ฒ๋ฆฌ๊ณ ์ฆ์ ์๋ก์ด state๋ก ๋ค์ ๋ ๋๋ง์ ์๋ํฉ๋๋ค. ์ด ํจํด์ ๊ฑฐ์ ํ์ํ์ง ์์ง๋ง **์ด์ ๋ ๋๋ง์ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค**. [์๋ ์์๋ฅผ ์ฐธ๊ณ ํ์ธ์.](#storing-information-from-previous-renders)
* Strict Mode์์ React๋ [์๋์น์์ ๋ถ์๋ฌผ์ ์ฐพ๊ธฐ ์ํด](#my-initializer-or-updater-function-runs-twice) **์
๋ฐ์ดํฐ ํจ์๋ฅผ ๋ ๋ฒ ํธ์ถํฉ๋๋ค**. ์ด๋ ๊ฐ๋ฐ ํ๊ฒฝ ์ ์ฉ ๋์์ด๋ฉฐ ํ๋ก๋์
ํ๊ฒฝ์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค. ๋ง์ฝ ์
๋ฐ์ดํฐ ํจ์๊ฐ ์์ํ๋ค๋ฉด(๊ทธ๋์ผ ํฉ๋๋ค) ๋์์ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค. ํธ์ถ ์ค ํ๋์ ๊ฒฐ๊ณผ๋ ๋ฌด์๋ฉ๋๋ค.
diff --git a/src/content/reference/react/useTransition.md b/src/content/reference/react/useTransition.md
index fdc6e3157..57d5de226 100644
--- a/src/content/reference/react/useTransition.md
+++ b/src/content/reference/react/useTransition.md
@@ -80,6 +80,8 @@ function TabContainer() {
* `startTransition`์ ์ ๋ฌํ๋ ํจ์๋ ๋๊ธฐ์์ด์ด์ผ ํฉ๋๋ค. React๋ ์ด ํจ์๋ฅผ ์ฆ์ ์คํํ์ฌ ์คํํ๋ ๋์ ๋ฐ์ํ๋ ๋ชจ๋ state ์
๋ฐ์ดํธ๋ฅผ Transition ์ผ๋ก ํ์ํฉ๋๋ค. ๋์ค์ ๋ ๋ง์ state ์
๋ฐ์ดํธ๋ฅผ ์ํํ๋ ค๊ณ ํ๋ฉด(์์: timeout), Transition ์ผ๋ก ํ์๋์ง ์์ต๋๋ค.
+* The `startTransition` function has a stable identity, so you will often see it omitted from effect dependencies, but including it will not cause the effect to fire. If the linter lets you omit a dependency without errors, it is safe to do. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
+
* Transition์ผ๋ก ํ์๋ state ์
๋ฐ์ดํธ๋ ๋ค๋ฅธ state ์
๋ฐ์ดํธ์ ์ํด ์ค๋จ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, Transition ๋ด์์ ์ฐจํธ ์ปดํฌ๋ํธ๋ฅผ ์
๋ฐ์ดํธํ ๋ค์ ์ฐจํธ๊ฐ ๋ค์ ๋ ๋๋ง ๋๋ ๋์ค์ ์
๋ ฅ์ ์์ํ๋ฉด React๋ ์
๋ ฅ ์
๋ฐ์ดํธ๋ฅผ ์ฒ๋ฆฌํ ํ ์ฐจํธ ์ปดํฌ๋ํธ์์ ๋ ๋๋ง ์์
์ ๋ค์ ์์ํฉ๋๋ค.
* Transition ์
๋ฐ์ดํธ๋ ํ
์คํธ ์
๋ ฅ์ ์ ์ดํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
diff --git a/src/content/reference/rsc/server-actions.md b/src/content/reference/rsc/server-actions.md
index 835df3dea..59c08a06d 100644
--- a/src/content/reference/rsc/server-actions.md
+++ b/src/content/reference/rsc/server-actions.md
@@ -53,7 +53,7 @@ React๊ฐ `EmptyNote` ์๋ฒ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ ๋, `createNoteAction`
export default function Button({onClick}) {
console.log(onClick);
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
- return
+ return
}
```