diff --git a/.eslintrc b/.eslintrc index 7bc6ab933..935fa2f23 100644 --- a/.eslintrc +++ b/.eslintrc @@ -9,7 +9,8 @@ "react-hooks/exhaustive-deps": "error", "react/no-unknown-property": ["error", {"ignore": ["meta"]}], "react-compiler/react-compiler": "error", - "local-rules/lint-markdown-code-blocks": "error" + "local-rules/lint-markdown-code-blocks": "error", + "no-trailing-spaces": "error" }, "env": { "node": true, diff --git a/next.config.js b/next.config.js index f8ec196e1..c8d7bf0ed 100644 --- a/next.config.js +++ b/next.config.js @@ -22,10 +22,15 @@ const nextConfig = { async rewrites() { return { beforeFiles: [ + // Explicit .md extension also serves markdown + { + source: '/:path*.md', + destination: '/api/md/:path*', + }, // Serve markdown when Accept header prefers text/markdown // Useful for LLM agents - https://www.skeptrune.com/posts/use-the-accept-header-to-serve-markdown-instead-of-html-to-llms/ { - source: '/:path((?!llms.txt).*)', + source: '/:path((?!llms\\.txt|api/md).*)', has: [ { type: 'header', @@ -35,11 +40,6 @@ const nextConfig = { ], destination: '/api/md/:path*', }, - // Explicit .md extension also serves markdown - { - source: '/:path*.md', - destination: '/api/md/:path*', - }, ], }; }, diff --git a/public/images/docs/scientists/1bX5QH6.jpg b/public/images/docs/scientists/1bX5QH6.jpg new file mode 100644 index 000000000..630b91bd2 Binary files /dev/null and b/public/images/docs/scientists/1bX5QH6.jpg differ diff --git a/public/images/docs/scientists/1bX5QH6b.jpg b/public/images/docs/scientists/1bX5QH6b.jpg new file mode 100644 index 000000000..7bd074365 Binary files /dev/null and b/public/images/docs/scientists/1bX5QH6b.jpg differ diff --git a/public/images/docs/scientists/1bX5QH6s.jpg b/public/images/docs/scientists/1bX5QH6s.jpg new file mode 100644 index 000000000..0bc3a6f40 Binary files /dev/null and b/public/images/docs/scientists/1bX5QH6s.jpg differ diff --git a/public/images/docs/scientists/2heNQDcm.jpg b/public/images/docs/scientists/2heNQDcm.jpg new file mode 100644 index 000000000..ecc8ab394 Binary files /dev/null and b/public/images/docs/scientists/2heNQDcm.jpg differ diff --git a/public/images/docs/scientists/3aIiwfm.jpg b/public/images/docs/scientists/3aIiwfm.jpg new file mode 100644 index 000000000..e93d8c802 Binary files /dev/null and b/public/images/docs/scientists/3aIiwfm.jpg differ diff --git a/public/images/docs/scientists/5qwVYb1.jpeg b/public/images/docs/scientists/5qwVYb1.jpeg new file mode 100644 index 000000000..cd8b4e556 Binary files /dev/null and b/public/images/docs/scientists/5qwVYb1.jpeg differ diff --git a/public/images/docs/scientists/6o5Vuyu.jpg b/public/images/docs/scientists/6o5Vuyu.jpg new file mode 100644 index 000000000..941563f8d Binary files /dev/null and b/public/images/docs/scientists/6o5Vuyu.jpg differ diff --git a/public/images/docs/scientists/7vQD0fPb.jpg b/public/images/docs/scientists/7vQD0fPb.jpg new file mode 100644 index 000000000..71baab951 Binary files /dev/null and b/public/images/docs/scientists/7vQD0fPb.jpg differ diff --git a/public/images/docs/scientists/7vQD0fPs.jpg b/public/images/docs/scientists/7vQD0fPs.jpg new file mode 100644 index 000000000..5da6b45f1 Binary files /dev/null and b/public/images/docs/scientists/7vQD0fPs.jpg differ diff --git a/public/images/docs/scientists/9EAYZrtl.jpg b/public/images/docs/scientists/9EAYZrtl.jpg new file mode 100644 index 000000000..7313ffdb2 Binary files /dev/null and b/public/images/docs/scientists/9EAYZrtl.jpg differ diff --git a/public/images/docs/scientists/AlHTAdDm.jpg b/public/images/docs/scientists/AlHTAdDm.jpg new file mode 100644 index 000000000..735c29cd5 Binary files /dev/null and b/public/images/docs/scientists/AlHTAdDm.jpg differ diff --git a/public/images/docs/scientists/DgXHVwul.jpg b/public/images/docs/scientists/DgXHVwul.jpg new file mode 100644 index 000000000..a9dba869c Binary files /dev/null and b/public/images/docs/scientists/DgXHVwul.jpg differ diff --git a/public/images/docs/scientists/FJeJR8M.jpg b/public/images/docs/scientists/FJeJR8M.jpg new file mode 100644 index 000000000..433fc3503 Binary files /dev/null and b/public/images/docs/scientists/FJeJR8M.jpg differ diff --git a/public/images/docs/scientists/HMFmH6m.jpg b/public/images/docs/scientists/HMFmH6m.jpg new file mode 100644 index 000000000..ac0a5f6c3 Binary files /dev/null and b/public/images/docs/scientists/HMFmH6m.jpg differ diff --git a/public/images/docs/scientists/IOjWm71s.jpg b/public/images/docs/scientists/IOjWm71s.jpg new file mode 100644 index 000000000..af912e34b Binary files /dev/null and b/public/images/docs/scientists/IOjWm71s.jpg differ diff --git a/public/images/docs/scientists/JBbMpWY.jpg b/public/images/docs/scientists/JBbMpWY.jpg new file mode 100644 index 000000000..a59002bca Binary files /dev/null and b/public/images/docs/scientists/JBbMpWY.jpg differ diff --git a/public/images/docs/scientists/K9HVAGHl.jpg b/public/images/docs/scientists/K9HVAGHl.jpg new file mode 100644 index 000000000..03894f397 Binary files /dev/null and b/public/images/docs/scientists/K9HVAGHl.jpg differ diff --git a/public/images/docs/scientists/MK3eW3Am.jpg b/public/images/docs/scientists/MK3eW3Am.jpg new file mode 100644 index 000000000..53287dd02 Binary files /dev/null and b/public/images/docs/scientists/MK3eW3Am.jpg differ diff --git a/public/images/docs/scientists/MK3eW3As.jpg b/public/images/docs/scientists/MK3eW3As.jpg new file mode 100644 index 000000000..43244d0c5 Binary files /dev/null and b/public/images/docs/scientists/MK3eW3As.jpg differ diff --git a/public/images/docs/scientists/Mx7dA2Y.jpg b/public/images/docs/scientists/Mx7dA2Y.jpg new file mode 100644 index 000000000..ee41fbbaf Binary files /dev/null and b/public/images/docs/scientists/Mx7dA2Y.jpg differ diff --git a/public/images/docs/scientists/OKS67lhb.jpg b/public/images/docs/scientists/OKS67lhb.jpg new file mode 100644 index 000000000..71d2917a7 Binary files /dev/null and b/public/images/docs/scientists/OKS67lhb.jpg differ diff --git a/public/images/docs/scientists/OKS67lhm.jpg b/public/images/docs/scientists/OKS67lhm.jpg new file mode 100644 index 000000000..9fe8f6307 Binary files /dev/null and b/public/images/docs/scientists/OKS67lhm.jpg differ diff --git a/public/images/docs/scientists/OKS67lhs.jpg b/public/images/docs/scientists/OKS67lhs.jpg new file mode 100644 index 000000000..fb3cf212c Binary files /dev/null and b/public/images/docs/scientists/OKS67lhs.jpg differ diff --git a/public/images/docs/scientists/QIrZWGIs.jpg b/public/images/docs/scientists/QIrZWGIs.jpg new file mode 100644 index 000000000..2bfa8ab82 Binary files /dev/null and b/public/images/docs/scientists/QIrZWGIs.jpg differ diff --git a/public/images/docs/scientists/QwUKKmF.jpg b/public/images/docs/scientists/QwUKKmF.jpg new file mode 100644 index 000000000..05aa061ea Binary files /dev/null and b/public/images/docs/scientists/QwUKKmF.jpg differ diff --git a/public/images/docs/scientists/RCwLEoQm.jpg b/public/images/docs/scientists/RCwLEoQm.jpg new file mode 100644 index 000000000..4d7d0b6df Binary files /dev/null and b/public/images/docs/scientists/RCwLEoQm.jpg differ diff --git a/public/images/docs/scientists/Sd1AgUOm.jpg b/public/images/docs/scientists/Sd1AgUOm.jpg new file mode 100644 index 000000000..b81b83d21 Binary files /dev/null and b/public/images/docs/scientists/Sd1AgUOm.jpg differ diff --git a/public/images/docs/scientists/Y3utgTi.jpg b/public/images/docs/scientists/Y3utgTi.jpg new file mode 100644 index 000000000..8d44e4fed Binary files /dev/null and b/public/images/docs/scientists/Y3utgTi.jpg differ diff --git a/public/images/docs/scientists/YfeOqp2b.jpg b/public/images/docs/scientists/YfeOqp2b.jpg new file mode 100644 index 000000000..44e0c65cb Binary files /dev/null and b/public/images/docs/scientists/YfeOqp2b.jpg differ diff --git a/public/images/docs/scientists/YfeOqp2s.jpg b/public/images/docs/scientists/YfeOqp2s.jpg new file mode 100644 index 000000000..19ef15704 Binary files /dev/null and b/public/images/docs/scientists/YfeOqp2s.jpg differ diff --git a/public/images/docs/scientists/ZF6s192.jpg b/public/images/docs/scientists/ZF6s192.jpg new file mode 100644 index 000000000..f50c7e348 Binary files /dev/null and b/public/images/docs/scientists/ZF6s192.jpg differ diff --git a/public/images/docs/scientists/ZF6s192m.jpg b/public/images/docs/scientists/ZF6s192m.jpg new file mode 100644 index 000000000..056f8d52b Binary files /dev/null and b/public/images/docs/scientists/ZF6s192m.jpg differ diff --git a/public/images/docs/scientists/ZfQOOzfl.jpg b/public/images/docs/scientists/ZfQOOzfl.jpg new file mode 100644 index 000000000..5c9e249bd Binary files /dev/null and b/public/images/docs/scientists/ZfQOOzfl.jpg differ diff --git a/public/images/docs/scientists/aTtVpES.jpg b/public/images/docs/scientists/aTtVpES.jpg new file mode 100644 index 000000000..00e09d093 Binary files /dev/null and b/public/images/docs/scientists/aTtVpES.jpg differ diff --git a/public/images/docs/scientists/aeO3rpIl.jpg b/public/images/docs/scientists/aeO3rpIl.jpg new file mode 100644 index 000000000..3b535b072 Binary files /dev/null and b/public/images/docs/scientists/aeO3rpIl.jpg differ diff --git a/public/images/docs/scientists/bE7W1jis.jpg b/public/images/docs/scientists/bE7W1jis.jpg new file mode 100644 index 000000000..a15a897ea Binary files /dev/null and b/public/images/docs/scientists/bE7W1jis.jpg differ diff --git a/public/images/docs/scientists/dB2LRbj.jpg b/public/images/docs/scientists/dB2LRbj.jpg new file mode 100644 index 000000000..f2ac04825 Binary files /dev/null and b/public/images/docs/scientists/dB2LRbj.jpg differ diff --git a/public/images/docs/scientists/jA8hHMpm.jpg b/public/images/docs/scientists/jA8hHMpm.jpg new file mode 100644 index 000000000..ba2168f85 Binary files /dev/null and b/public/images/docs/scientists/jA8hHMpm.jpg differ diff --git a/public/images/docs/scientists/kxsph5Cl.jpg b/public/images/docs/scientists/kxsph5Cl.jpg new file mode 100644 index 000000000..f33360729 Binary files /dev/null and b/public/images/docs/scientists/kxsph5Cl.jpg differ diff --git a/public/images/docs/scientists/lICfvbD.jpg b/public/images/docs/scientists/lICfvbD.jpg new file mode 100644 index 000000000..67393f31e Binary files /dev/null and b/public/images/docs/scientists/lICfvbD.jpg differ diff --git a/public/images/docs/scientists/lrWQx8ls.jpg b/public/images/docs/scientists/lrWQx8ls.jpg new file mode 100644 index 000000000..bc0708bd0 Binary files /dev/null and b/public/images/docs/scientists/lrWQx8ls.jpg differ diff --git a/public/images/docs/scientists/mynHUSas.jpg b/public/images/docs/scientists/mynHUSas.jpg new file mode 100644 index 000000000..e369df8c5 Binary files /dev/null and b/public/images/docs/scientists/mynHUSas.jpg differ diff --git a/public/images/docs/scientists/okTpbHhm.jpg b/public/images/docs/scientists/okTpbHhm.jpg new file mode 100644 index 000000000..a96c5c03c Binary files /dev/null and b/public/images/docs/scientists/okTpbHhm.jpg differ diff --git a/public/images/docs/scientists/rN7hY6om.jpg b/public/images/docs/scientists/rN7hY6om.jpg new file mode 100644 index 000000000..3c7afe1f9 Binary files /dev/null and b/public/images/docs/scientists/rN7hY6om.jpg differ diff --git a/public/images/docs/scientists/rTqKo46l.jpg b/public/images/docs/scientists/rTqKo46l.jpg new file mode 100644 index 000000000..4a0b3dc3b Binary files /dev/null and b/public/images/docs/scientists/rTqKo46l.jpg differ diff --git a/public/images/docs/scientists/szV5sdGb.jpg b/public/images/docs/scientists/szV5sdGb.jpg new file mode 100644 index 000000000..8d6579402 Binary files /dev/null and b/public/images/docs/scientists/szV5sdGb.jpg differ diff --git a/public/images/docs/scientists/szV5sdGs.jpg b/public/images/docs/scientists/szV5sdGs.jpg new file mode 100644 index 000000000..fc3c34260 Binary files /dev/null and b/public/images/docs/scientists/szV5sdGs.jpg differ diff --git a/public/images/docs/scientists/wIdGuZwm.png b/public/images/docs/scientists/wIdGuZwm.png new file mode 100644 index 000000000..5f482def6 Binary files /dev/null and b/public/images/docs/scientists/wIdGuZwm.png differ diff --git a/public/images/docs/scientists/yXOvdOSs.jpg b/public/images/docs/scientists/yXOvdOSs.jpg new file mode 100644 index 000000000..0a3269510 Binary files /dev/null and b/public/images/docs/scientists/yXOvdOSs.jpg differ diff --git a/public/images/docs/scientists/z08o2TS.jpg b/public/images/docs/scientists/z08o2TS.jpg new file mode 100644 index 000000000..42a0a00ef Binary files /dev/null and b/public/images/docs/scientists/z08o2TS.jpg differ diff --git a/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md b/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md index 437355490..8263a8648 100644 --- a/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md +++ b/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md @@ -49,19 +49,31 @@ React 컴파일러는 더 이상 연구 프로젝트가 아닙니다. 컴파일 `action` 함수는 동기적 또는 비동기적으로 실행할 수 있습니다. 클라이언트 측에서 표준 자바스크립트를 사용하여 정의하거나, [`'use server'`](/reference/rsc/use-server)라는 지시어를 사용하여 서버에서 정의할 수 있습니다. 액션을 사용할 때, React는 [`useFormStatus`](/reference/react-dom/hooks/useFormStatus), [`useActionState`](/reference/react/useActionState)와 같은 Hook을 제공하여 데이터 제출의 생명주기를 관리하고 현재 폼의 State와 응답에 접근할 수 있습니다. +<<<<<<< HEAD 기본적으로 액션은 [트랜지션](/reference/react/useTransition) 내에서 제출되어 현재 페이지가 상호작용을 하는 동안 액션을 처리합니다. 액션은 비동기 함수를 지원하므로, 트랜지션 내에서 `async`/`await`을 사용할 수 있도록 추가했습니다. 이를 통해 `fetch`와 같은 비동기 요청이 시작되면 트랜지션의 `isPending` State를 사용하여 대기 중인 UI를 표시하고, 업데이트가 적용될 때까지 대기 중인 UI를 계속 보여줄 수 있습니다. +======= +By default, Actions are submitted within a [transition](/reference/react/useTransition), keeping the current page interactive while the action is processing. Since Actions support async functions, we've also added the ability to use `async/await` in transitions. This allows you to show pending UI with the `isPending` state of a transition when an async request like `fetch` starts, and show the pending UI all the way through the update being applied. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 액션과 함께, 낙관적 State 업데이트를 관리하기 위한 [`useOptimistic`](/reference/react/useOptimistic)이라는 기능을 소개합니다. 이 Hook을 사용하여 최종 State가 커밋되면 자동으로 되돌릴 수 있는 일시적인 업데이트를 적용할 수 있습니다. 액션의 경우, 제출이 성공적이라고 가정하고 클라이언트에서 데이터의 최종 State를 낙관적으로 업데이트할 수 있습니다. 그리고 서버에서 받은 데이터를 통해 값을 되돌릴 수 있습니다. 이는 일반적인 `async`/`await` 방식을 사용하여 작동하므로, 클라이언트에서 `fetch`를 사용하든 서버에서 서버 액션을 사용하든 동일하게 작동합니다. 라이브러리 제작자는 각자의 컴포넌트에서 `useTransition`를 사용하여 사용자 지정 `action={fn}` Props를 구현할 수 있습니다. 우리의 의도는 라이브러리가 컴포넌트 API를 설계할 때 액션 패턴을 채택하여 React 개발자들에게 일관적인 경험을 제공하는 것입니다. 예를 들어, 라이브러리에서 ``와 같은 컴포넌트를 제공하는 경우, ``와 같은 API도 노출하는 것을 고려해 보세요. +<<<<<<< HEAD 우리는 처음에 서버 액션을 클라이언트-서버 사이 데이터 전송에 중점을 두었지만, React의 철학은 모둔 플랫폼과 환경에서 동일한 프로그래밍 모델을 제공하는 것입니다. 가능하다면 클라이언트의 기능을 소개한 경우 해당 기능이 서버에서도 작동하도록 하고, 그 반대의 경우도 마찬가지입니다. 이 철학을 통해 애플리케이션이 실행되는 위치와 관계없이 작동하는 단일 API 모음을 생성하여, 이후 다른 환경으로 업그레이드 하기 쉽게 만들 수 있습니다. +======= +While we initially focused on Server Actions for client-server data transfer, our philosophy for React is to provide the same programming model across all platforms and environments. When possible, if we introduce a feature on the client, we aim to make it also work on the server, and vice versa. This philosophy allows us to create a single set of APIs that work no matter where your app runs, making it easier to upgrade to different environments later. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 액션은 현재 실험적 채널에서 이용하실 수 있으며, React의 다음 배포에서 제공될 예정입니다. ## React Canary의 새로운 기능 {/*new-features-in-react-canary*/} +<<<<<<< HEAD 우리는 [React Canary](/blog/2023/05/03/react-canaries)에서 새로운 안정적 기능들이 최종 설계에 가까워질 때마다 각각을 선택적으로 채택할 수 있도록 소개했습니다. 그리고 이를 안정적인 시멘틱 버저닝으로 배포되기 이전에 사용할 수 있습니다. +======= +We introduced [React Canaries](/blog/2023/05/03/react-canaries) as an option to adopt individual new stable features as soon as their design is close to final, before they’re released in a stable semver version. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a Canary는 React의 개발 방식을 변경하는 것입니다. 이전에는 기능들이 비공개로 Meta 내부에서 연구되고 개발되었기 때문에 사용자는 그 결과물이 안정적인 버전으로 배포되었을 때만 볼 수 있었습니다. 이제 Canary와 함께 커뮤니티의 도움을 받아 React Labs 블로그 시리즈에서 공유하고 있는 기능을 완성하고자 공개적으로 개발하고 있습니다. 이는 여러분들이 새로운 기능이 완성된 이후가 아닌 완료되는 과정에서 곧바로 알 수 있다는 것을 의미합니다. @@ -75,7 +87,11 @@ React 서버 컴포넌트, 에셋 불러오기, 문서 메타데이터 및 액 - **액션**: 앞서 언급한 대로, 클라이언트에서 서버로 데이터를 전송하는 것을 관리하기 위해 액션을 추가했습니다. [`
`](/reference/react-dom/components/form)과 같은 엘리먼트에 `action`을 추가할 수 있으며, [`useFormStatus`](/reference/react-dom/hooks/useFormStatus)를 사용하여 진행 상황에 접근하고, [`useActionState`](/reference/react/useActionState)를 사용하여 결과를 처리하며, [`useOptimistic`](/reference/react/useOptimistic)를 사용하여 UI를 낙관적으로 업데이트할 수 있습니다. +<<<<<<< HEAD 이러한 모든 기능은 함께 작동하기 때문에, 이들을 각각 안정적 채널에 배포하기는 어렵습니다. 폼 State에 접근하는 보조 Hook 없이 액션을 배포하는 것은 액션의 실제 유용성을 제한할 것입니다. 서버 액션을 통합하지 않으면서 React 서버 컴포넌트를 도입하면 서버에서 데이터를 수정하기에 복잡해질 것입니다. +======= +Since all of these features work together, it’s difficult to release them in the Stable channel individually. Releasing Actions without the complementary hooks for accessing form states would limit the practical usability of Actions. Introducing React Server Components without integrating Server Actions would complicate modifying data on the server. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 저희는 이러한 기능들을 안정적 채널에 배포하기 전에, 이들이 함께 작동하고 개발자가 프로덕션 단계에서 사용하기 위해 필요한 모든 것을 갖추었는지 보장해야 합니다. React Canary를 통해 개발자는 이런 기능을 개별적으로 개발하고, 전체 기능 목록이 완성되기 전까지 점진적으로 안정된 API를 배포할 수 있습니다. diff --git a/src/content/blog/2024/04/25/react-19-upgrade-guide.md b/src/content/blog/2024/04/25/react-19-upgrade-guide.md index 5ba723288..d450675a6 100644 --- a/src/content/blog/2024/04/25/react-19-upgrade-guide.md +++ b/src/content/blog/2024/04/25/react-19-upgrade-guide.md @@ -20,7 +20,11 @@ React 19에 추가된 개선 사항들로 인해 일부 주요한 변경 사항< #### React 18.3도 함께 출시되었습니다 {/*react-18-3*/} +<<<<<<< HEAD React 19으로의 업그레이드를 더 쉽게 돕기 위해 `react@18.3`을 출시했습니다. 이 버전은 18.2와 동일하지만, 더 이상 사용되지 않는 API 및 React 19에 필요한 변경 사항에 대한 경고를 추가했습니다. +======= +To help make the upgrade to React 19 easier, we've published a `react@18.3` release that is identical to 18.2 but adds warnings for deprecated APIs and other changes that are needed for React 19. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a React 19로 업그레이드하기 전에 먼저 React 18.3으로 업데이트하여 잠재적인 문제를 미리 파악하는 것을 권장합니다. @@ -108,7 +112,11 @@ yarn add --exact @types/react@^19.0.0 @types/react-dom@^19.0.0 npx codemod@latest react/19/migration-recipe ``` +<<<<<<< HEAD 이 명령어를 실행하면 `react-codemod`에서 아래 Codemod가 실행됩니다. +======= +This will run the following codemods from `react-codemod`: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a - [`replace-reactdom-render`](https://github.com/reactjs/react-codemod?tab=readme-ov-file#replace-reactdom-render) - [`replace-string-ref`](https://github.com/reactjs/react-codemod?tab=readme-ov-file#replace-string-ref) - [`replace-act-import`](https://github.com/reactjs/react-codemod?tab=readme-ov-file#replace-act-import) @@ -119,7 +127,11 @@ npx codemod@latest react/19/migration-recipe +<<<<<<< HEAD Codemod가 포함된 변경 사항에는 아래와 같이 명령어가 함께 제공됩니다. +======= +Changes that include a codemod include the command below. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 사용할 수 있는 모든 Codemod 목록은 [`react-codemod` 저장소](https://github.com/reactjs/react-codemod)를 참고하세요. @@ -127,7 +139,11 @@ Codemod가 포함된 변경 사항에는 아래와 같이 명령어가 함께 ### 렌더링 중에 발생한 오류는 re-throw 하지 않음 {/*errors-in-render-are-not-re-thrown*/} +<<<<<<< HEAD 이전 버전의 React에서는 렌더링 중에 발생한 오류를 잡아서 re-throw 했습니다. 개발 모드DEV에서는 `console.error`로도 로그를 출력하여 오류 로그가 중복되는 문제가 있었습니다. +======= +In previous versions of React, errors thrown during render were caught and rethrown. In DEV, we would also log to `console.error`, resulting in duplicate error logs. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a React 19에서는 [오류 처리 방식을 개선하여](/blog/2024/04/25/react-19#error-handling) 더 이상 오류를 re-throw 하지 않음으로써 중복 로그를 줄였습니다. @@ -348,7 +364,11 @@ npm install react-shallow-renderer --save-dev ##### Shallow 렌더링 재고 권장 {/*please-reconsider-shallow-rendering*/} +<<<<<<< HEAD Shallow 렌더링은 React 내부 구현에 의존하며 향후 React 업그레이드를 방해할 수 있습니다. 테스트를 [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) 또는 [@testing-library/react-native](https://testing-library.com/docs/react-native-testing-library/intro)로 마이그레이션하는 것을 권장합니다. +======= +Shallow rendering depends on React internals and can block you from future upgrades. We recommend migrating your tests to [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/) or [@testing-library/react-native](https://testing-library.com/docs/react-native-testing-library/intro). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a @@ -465,7 +485,11 @@ npx codemod@latest react/19/replace-reactdom-render #### 제거됨: `ReactDOM.findDOMNode` {/*removed-reactdom-finddomnode*/} +<<<<<<< HEAD `ReactDOM.findDOMNode`는 [2018년 10월 (v16.6.0)](https://legacy.reactjs.org/blog/2018/10/23/react-v-16-6.html#deprecations-in-strictmode)부터 더 이상 권장되지 않습니다. +======= +`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). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a `findDOMNode`는 레거시 코드의 해결책이었지만 실행 속도가 느리고 리팩토링에 취약하며 첫 번째 자식만 반환하는 등 많은 문제가 있어 제거됩니다 ([이곳](https://legacy.reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage)에서 더 알아보기). `ReactDOM.findDOMNode` 대신 [DOM refs](/learn/manipulating-the-dom-with-refs)로 대체하여 사용할 수 있습니다. @@ -551,7 +575,11 @@ React 19에서는 컴포넌트가 일시 중단되면 fallback을 먼저 반영 ### UMD 빌드 제거됨 {/*umd-builds-removed*/} +<<<<<<< HEAD 과거에는 빌드 과정 없이도 React를 불러올 수 있는 편리한 방법으로 UMD가 널리 사용되었습니다. 하지만 이제는 HTML 문서에서 스크립트로 모듈을 불러올 수 있는 더 현대적인 대안이 존재합니다. React 19부터는 테스트 및 릴리스 과정의 복잡성을 줄이기 위해 UMD 빌드를 더 이상 제공하지 않습니다. +======= +UMD was widely used in the past as a convenient way to load React without a build step. Now, there are modern alternatives for loading modules as scripts in HTML documents. Starting with React 19, React will no longer produce UMD builds to reduce the complexity of its testing and release process. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a React 19를 script 태그로 불러오려면 [esm.sh](https://esm.sh/)와 같은 ESM 기반 CDN을 사용할 것을 권장합니다. @@ -569,7 +597,11 @@ React 19를 script 태그로 불러오려면 [esm.sh](https://esm.sh/)와 같은 [버전 관리 정책](https://react.dev/community/versioning-policy#what-counts-as-a-breaking-change)에 따라 이러한 업데이트는 중요 변경 사항으로 간주하지 않으며 어떻게 업그레이드해야 하는지에 대한 문서도 제공되지 않습니다. 권장 사항은 내부 구현에 의존하는 코드를 모두 제거하는 것입니다. +<<<<<<< HEAD 내부 구현 사용의 영향을 명확히 보여주기 위해 `SECRET_INTERNALS` 접미사Suffix를 다음과 같이 변경했습니다. +======= +To reflect the impact of using internals, we have renamed the `SECRET_INTERNALS` suffix to: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a `_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` diff --git a/src/content/blog/2024/12/05/react-19.md b/src/content/blog/2024/12/05/react-19.md index 57ce3ad5d..39467f344 100644 --- a/src/content/blog/2024/12/05/react-19.md +++ b/src/content/blog/2024/12/05/react-19.md @@ -176,7 +176,11 @@ const [error, submitAction, isPending] = useActionState( ); ``` +<<<<<<< HEAD `useActionState`는 함수(액션)를 받아서 이를 호출하는 래핑된 액션을 반환합니다. 이것이 작동하는 이유는, 액션들이 조합 가능하기 때문입니다. 래핑된 액션이 호출되면 `useActionState`는 액션의 마지막 결과를 `data`로 액션의 대기 상태를 `pending`으로 반환합니다. +======= +`useActionState` accepts a function (the "Action"), and returns a wrapped Action to call. This works because Actions compose. When the wrapped Action is called, `useActionState` will return the last result of the Action as `data`, and the pending state of the Action as `pending`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a @@ -309,8 +313,13 @@ function Heading({children}) { return null; } +<<<<<<< HEAD // 조기 반환으로 인하여, // `useContext`는 동작하지 않습니다. +======= + // This would not work with useContext + // because of the early return. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a const theme = use(ThemeContext); return (

@@ -330,7 +339,11 @@ function Heading({children}) { - [`prerender`](/reference/react-dom/static/prerender) - [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream) +<<<<<<< HEAD 이 새로운 API들은 `renderToString`보다 더 나아가서 정적 HTML 생성을 위해 데이터가 로드될 때까지 기다립니다. 이들은 Node.js Streams와 Web Streams와 같은 스트리밍 환경과 호환되도록 설계되었습니다. 예를 들어, Web Stream 환경에서는 `prerender`를 사용하여 React 트리를 정적 HTML로 미리 렌더링할 수 있습니다. +======= +These new APIs improve on `renderToString` by waiting for data to load for static HTML generation. They are designed to work with streaming environments like Node.js Streams and Web Streams. For example, in a Web Stream environment, you can prerender a React tree to static HTML with `prerender`: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js import { prerender } from 'react-dom/static'; @@ -355,14 +368,22 @@ Prerender API는 정적 HTML 스트림이 반환되기 전에 데이터가 로 서버 컴포넌트는 번들링 전에 클라이언트 애플리케이션 또는 SSR 서버와 분리된 환경에서 컴포넌트를 미리 렌더링할 수 있는 새로운 옵션입니다. 이 별도의 환경이 React 서버 컴포넌트에서 "서버"입니다. 서버 컴포넌트는 CI 서버에서 빌드 시 한 번 실행하거나 웹 서버를 사용하여 각 요청에 대해 실행할 수 있습니다. +<<<<<<< HEAD React 19는 Canary 채널에서 포함된 모든 React 서버 컴포넌트 기능을 포함하고 있습니다. 이는 서버 컴포넌트가 포함된 라이브러리들이 이제 [풀스택 React 아키텍처](/learn/creating-a-react-app#which-features-make-up-the-react-teams-full-stack-architecture-vision)를 지원하는 프레임워크에서 `react-server` [export 조건](https://github.com/reactjs/rfcs/blob/main/text/0227-server-module-conventions.md#react-server-conditional-exports)을 사용하여 React 19를 향한 상호 의존성Peer Dependencies으로 지정할 수 있음을 의미합니다. +======= +React 19 includes all of the React Server Components features included from the Canary channel. This means libraries that ship with Server Components can now target React 19 as a peer dependency with a `react-server` [export condition](https://github.com/reactjs/rfcs/blob/main/text/0227-server-module-conventions.md#react-server-conditional-exports) for use in frameworks that support the [Full-stack React Architecture](/learn/creating-a-react-app#which-features-make-up-the-react-teams-full-stack-architecture-vision). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 서버 컴포넌트에 대한 지원을 어떻게 구축하나요? {/*how-do-i-build-support-for-server-components*/} +<<<<<<< HEAD React 19에서 React 서버 컴포넌트는 안정적이며 마이너 버전 간에는 깨지지 않지만, React 서버 컴포넌트 번들러나 프레임워크를 구현하는 데 사용되는 기본 API는 semver를 따르지 않고 React 19.x의 마이너 버전 간에는 변경될 수 있습니다. +======= +While React Server Components in React 19 are stable and will not break between minor versions, the underlying APIs used to implement a React Server Components bundler or framework do not follow semver and may break between minors in React 19.x. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a React 서버 컴포넌트를 지원하기 위해, 특정 React 버전에 고정하거나 Canary 릴리스를 사용하는 것을 권장합니다. 우리는 앞으로 번들러와 프레임워크와 협력하여 React 서버 컴포넌트를 구현하는 데 사용되는 API를 안정화할 계획입니다. @@ -521,7 +542,11 @@ function App({children}) { /> ``` +<<<<<<< HEAD 컴포넌트가 마운트 해제될 때, React는 `ref` 콜백으로부터 클린업 함수를 호출할 것입니다. 이는 DOM Ref, 클래스 컴포넌트 Ref 그리고 `useImperativeHandle` 모두 해당합니다. +======= +When the component unmounts, React will call the cleanup function returned from the `ref` callback. This works for DOM refs, refs to class components, and `useImperativeHandle`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a @@ -564,7 +589,11 @@ function Search({deferredValue}) { ### 메타데이터 문서에 대한 지원 {/*support-for-metadata-tags*/} +<<<<<<< HEAD HTML에서는 ``, `<link>`, `<meta>`와 같은 문서 메타 데이터 태그들이 문서의 `<head>` 섹션에 배치되어야 합니다. 그러나 React에서는 애플리케이션에 적합한 메타 데이터를 결정하는 컴포넌트가 `<head>`를 렌더링하는 곳과 아주 멀리 떨어져 있을 수 있거나, React 자체에서 `<head>`를 전혀 렌더링하지 않을 수도 있습니다. 과거에는 이러한 엘리먼트들을 이펙트를 사용하여 수동으로 삽입하거나 [`react-helmet`](https://github.com/nfl/react-helmet)과 같은 라이브러리를 사용하여 처리해야 했으며, React 애플리케이션을 서버에서 렌더링할 때 주의 깊게 처리해야 했습니다. +======= +In HTML, document metadata tags like `<title>`, `<link>`, and `<meta>` are reserved for placement in the `<head>` section of the document. In React, the component that decides what metadata is appropriate for the app may be very far from the place where you render the `<head>` or React does not render the `<head>` at all. In the past, these elements would need to be inserted manually in an effect, or by libraries like [`react-helmet`](https://github.com/nfl/react-helmet), and required careful handling when server rendering a React application. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a React 19에서는 컴포넌트에서 문서 메타 데이터 태그를 네이티브로 렌더링할 수 있는 지원을 추가하고 있습니다. @@ -726,7 +755,11 @@ React 19에서는 `<head>` 및 `<body>`에서 예상치 못한 태그가 발견 ### 더 나은 에러 리포팅 {/*error-handling*/} +<<<<<<< HEAD React 19에서는 오류 처리를 개선하여 중복을 줄이고 잡힌 오류와 잡히지 않은 오류를 처리할 수 있는 옵션을 제공했습니다. 예를 들어, 에러 바운더리에 의해 잡힌 렌더링 중 오류가 발생할 경우, 이전에는 React가 오류를 두 번 던졌습니다 (원래 오류와 자동 복구에 실패한 후에 다시). 그리고 `console.error`를 호출하여 오류가 발생한 위치에 대한 정보를 출력했습니다. +======= +We improved error handling in React 19 to remove duplication and provide options for handling caught and uncaught errors. For example, when there's an error in render caught by an Error Boundary, previously React would throw the error twice (once for the original error, then again after failing to automatically recover), and then call `console.error` with info about where the error occurred. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 이에 따라 잡힌 오류마다 세 개의 오류가 발생하는 문제가 있었습니다. diff --git a/src/content/blog/2025/02/14/sunsetting-create-react-app.md b/src/content/blog/2025/02/14/sunsetting-create-react-app.md index f4ef59cd7..b949a19b0 100644 --- a/src/content/blog/2025/02/14/sunsetting-create-react-app.md +++ b/src/content/blog/2025/02/14/sunsetting-create-react-app.md @@ -11,7 +11,11 @@ description: 새로운 앱에 대한 Create React App 사용을 중단하며, <Intro> +<<<<<<< HEAD 새로운 앱에 대한 [Create React App](https://create-react-app.dev/) 사용을 중단하며, 기존 앱은 [프레임워크](#how-to-migrate-to-a-framework)나 Vite, Parcel, RSBuild 같은 빌드 도구로의 [마이그레이션](#how-to-migrate-to-a-build-tool)을 권장합니다. +======= +Today, we’re deprecating [Create React App](https://create-react-app.dev/) for new apps, and encouraging existing apps to migrate to a [framework](#how-to-migrate-to-a-framework), or to [migrate to a build tool](#how-to-migrate-to-a-build-tool) like Vite, Parcel, or RSBuild. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 또한 프레임워크가 프로젝트와 맞지 않거나, 자신만의 프레임워크를 구축하고 싶거나, 혹은 React가 어떻게 작동하는지 배우기 위해 React 앱을 처음부터 만들어 보고 싶은 사용자들을 위한 [문서](https://react.dev/learn/build-a-react-app-from-scratch)를 제공합니다. @@ -75,7 +79,11 @@ Vite, Parcel 또는 RSBuild로 시작하는 데 도움을 주기 위해 [React #### 프레임워크가 필요할까요? {/*do-i-need-a-framework*/} +<<<<<<< HEAD 대부분의 앱은 프레임워크를 사용하는 것이 유리하지만, React 앱을 처음부터 직접 구축해야 하는 타당한 경우도 있습니다. 일반적인 기준으로, 만약 앱에서 라우팅이 필요하다면 프레임워크를 사용하는 것이 더 나을 가능성이 큽니다. +======= +Most apps would benefit from a framework, but there are valid cases to build a React app from scratch. A good rule of thumb is if your app needs routing, you would probably benefit from a framework. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a Svelte에는 SvelteKit, Vue에는 Nuxt 그리고 Solid에는 SolidStart가 있듯이, React도 기본적으로 라우팅을 포함한 데이터 가져오기, 코드 분할 등의 기능을 통합한 [프레임워크 사용을 권장합니다.](#why-we-recommend-frameworks) 이렇게 하면 복잡한 설정을 직접 구성하거나, 사실상 자체 프레임워크를 만들어야 하는 부담을 피할 수 있습니다. diff --git a/src/content/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components.md b/src/content/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components.md index aa0edae26..6bdd93a47 100644 --- a/src/content/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components.md +++ b/src/content/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components.md @@ -176,7 +176,7 @@ The patches published today prevent stringifying the Server Function source code Secrets hardcoded in source code may be exposed, but runtime secrets such as `process.env.SECRET` are not affected. -The scope of the exposed code is limited to the code inside the Server Function, which may include other functions depending on the amount of inlining your bundler provides. +The scope of the exposed code is limited to the code inside the Server Function, which may include other functions depending on the amount of inlining your bundler provides. Always verify against production bundles. diff --git a/src/content/community/translations.md b/src/content/community/translations.md index 19147bcb5..2d61d4513 100644 --- a/src/content/community/translations.md +++ b/src/content/community/translations.md @@ -28,7 +28,11 @@ React 문서는 전 세계의 글로벌 커뮤니티에 의해 다양한 언어 ## 기여하는 방법 {/*how-to-contribute*/} +<<<<<<< HEAD 번역 작업에 기여할 수 있습니다! +======= +You can contribute to the translation efforts! +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 커뮤니티는 "react.dev"의 각 언어별 포크<sup>Fork</sup>에서 React 문서의 번역 작업을 수행합니다. 일반적인 번역 작업은 Markdown 파일을 직접 번역하고 PR을 생성하는 것을 포함합니다. 위의 "기여하기" 링크를 클릭하여 해당 언어의 GitHub 저장소로 이동하고, 지침을 따라 번역 작업에 도움을 주실 수 있습니다. diff --git a/src/content/learn/adding-interactivity.md b/src/content/learn/adding-interactivity.md index 1e63676f8..d7ab90d41 100644 --- a/src/content/learn/adding-interactivity.md +++ b/src/content/learn/adding-interactivity.md @@ -139,73 +139,73 @@ export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', - url: 'https://i.imgur.com/Mx7dA2Y.jpg', + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; ``` @@ -423,7 +423,7 @@ export default function Form() { artwork: { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', } }); @@ -531,7 +531,7 @@ export default function Form() { artwork: { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', } }); diff --git a/src/content/learn/build-a-react-app-from-scratch.md b/src/content/learn/build-a-react-app-from-scratch.md index f633ad369..d80d470c3 100644 --- a/src/content/learn/build-a-react-app-from-scratch.md +++ b/src/content/learn/build-a-react-app-from-scratch.md @@ -12,7 +12,11 @@ title: 처음부터 React 앱 만들기 #### 프레임워크 사용을 고려해 보세요 {/*consider-using-a-framework*/} +<<<<<<< HEAD React로 처음부터 시작하는 것은 React를 처음 사용하기에는 쉬운 방법이지만, 이 방식이 종종 자신만의 임시 프레임워크를 만드는 것과 다름없다는 점을 알아야 합니다. 요구사항이 발전함에 따라, 저희가 추천하는 프레임워크들이 이미 잘 개발하고 해결한 문제들을 직접 해결해야 할 수도 있습니다. +======= +Starting from scratch is an easy way to get started using React, but a major tradeoff to be aware of is that going this route is often the same as building your own adhoc framework. As your requirements evolve, you may need to solve more framework-like problems that our recommended frameworks already have well developed and supported solutions for. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 예를 들어, 나중에 앱이 서버 사이드 렌더링(SSR), 정적 사이트 생성(SSG), 또는 React 서버 컴포넌트<sup>RSC</sup>를 지원해야 한다면, 이 모든 것을 직접 구현해야 할 것입니다. 마찬가지로, 미래의 React 기능 중 프레임워크 수준의 통합이 필요한 기능이 있다면, 사용하고 싶을 때 직접 구현해야 합니다. @@ -132,12 +136,22 @@ GraphQL API에서 데이터를 가져온다면 다음을 사용할 것을 제안 * **React 서버 컴포넌트(RSC)** 를 사용하면 빌드 타임, 서버 전용, 대화형 컴포넌트를 단일 React 트리에서 혼합할 수 있습니다. RSC는 성능을 향상할 수 있지만, 현재는 설정하고 유지 관리하는 데 깊은 전문 지식이 필요합니다. [Parcel의 RSC 예시](https://github.com/parcel-bundler/rsc-examples)를 참조하세요. +<<<<<<< HEAD 프레임워크로 만들어진 앱이 라우트별로 렌더링 전략을 선택할 수 있도록, 렌더링 전략은 라우터와 통합되어야 합니다. 이렇게 하면 전체 앱을 다시 작성할 필요 없이 다양한 렌더링 전략을 사용할 수 있습니다. 예를 들어, 앱의 랜딩 페이지는 정적으로 생성되는 것(SSG)이 유리할 수 있지만, 콘텐츠 피드가 있는 페이지는 서버 측 렌더링이 가장 잘 작동할 수 있습니다. +======= +Your rendering strategies need to integrate with your router so apps built with your framework can choose the rendering strategy on a per-route level. This will enable different rendering strategies without having to rewrite your whole app. For example, the landing page for your app might benefit from being statically generated (SSG), while a page with a content feed might perform best with server-side rendering. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 올바른 라우트에 올바른 렌더링 전략을 사용하면 콘텐츠의 첫 바이트가 로드되는 시간([Time to First Byte](https://web.dev/articles/ttfb)), 첫 번째 콘텐츠가 렌더링 되는 시간([First Contentful Paint](https://web.dev/articles/fcp)), 그리고 앱의 가장 큰 시각적 콘텐츠가 렌더링되는 시간([Largest Contentful Paint](https://web.dev/articles/lcp))을 줄일 수 있습니다. ### 그리고 더... {/*and-more*/} +<<<<<<< HEAD 이것들은 새로운 앱을 처음부터 구축할 때 고려해야 할 기능들의 몇 가지 예시에 불과합니다. 맞닥뜨리게 될 많은 제약은 각 문제가 서로 얽혀 있고 익숙하지 않은 문제 영역에 대한 깊은 전문 지식을 요구할 수 있기 때문에 해결하기 어려울 수 있습니다. 이러한 문제들을 직접 해결하고 싶지 않다면, 이러한 기능을 바로 제공하는 [프레임워크로 시작](/learn/creating-a-react-app)할 수 있습니다. +======= +These are just a few examples of the features a new app will need to consider when building from scratch. Many limitations you'll hit can be difficult to solve as each problem is interconnected with the others and can require deep expertise in problem areas you may not be familiar with. + +If you don't want to solve these problems on your own, you can [get started with a framework](/learn/creating-a-react-app) that provides these features out of the box. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a diff --git a/src/content/learn/choosing-the-state-structure.md b/src/content/learn/choosing-the-state-structure.md index 05763485e..e4b13865e 100644 --- a/src/content/learn/choosing-the-state-structure.md +++ b/src/content/learn/choosing-the-state-structure.md @@ -1822,6 +1822,7 @@ button { margin: 10px; } <Recap> +<<<<<<< HEAD * 만약 두 state 변수가 항상 함께 업데이트된다면, 하나로 합치는 것을 고려해 보세요. * State 변수를 신중하게 선택하여 "불가능한" state를 만들지 않도록 하세요. * State를 업데이트할 때 실수할 가능성을 줄이도록 state를 구조화하세요. @@ -1829,6 +1830,15 @@ button { margin: 10px; } * 특별히 업데이트를 방지하려는 경우를 제외하고는 props를 state에 *넣지* 마세요. * 선택과 같은 UI 패턴의 경우, 객체 자체가 아닌 ID 또는 인덱스를 state에 유지하세요. * 깊게 중첩된 state를 업데이트하는 것이 복잡한 경우, 평탄하게 만들어 보세요. +======= +* If two state variables always update together, consider merging them into one. +* Choose your state variables carefully to avoid creating "impossible" states. +* Structure your state in a way that reduces the chances that you'll make a mistake updating it. +* Avoid redundant and duplicate state so that you don't need to keep it in sync. +* Don't put props *into* state unless you specifically want to prevent updates. +* For UI patterns like selection, keep ID or index in state instead of the object itself. +* If updating deeply nested state is complicated, try flattening it. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Recap> diff --git a/src/content/learn/creating-a-react-app.md b/src/content/learn/creating-a-react-app.md index 66def430b..36daaa314 100644 --- a/src/content/learn/creating-a-react-app.md +++ b/src/content/learn/creating-a-react-app.md @@ -104,7 +104,11 @@ Next.js의 App Router는 [Suspense와 데이터 조회](/blog/2022/03/29/react-v 앱에 기존 프레임워크에서 잘 제공되지 않는 제약 조건이 있거나, 자체 프레임워크를 구축하는 것을 선호하거나, React 앱의 기본 사항을 배우려는 경우 React 프로젝트를 처음부터 시작하는 데 사용할 수 있는 다른 옵션이 있습니다. +<<<<<<< HEAD 처음부터 시작하면 더 많은 유연성을 얻을 수 있지만 라우팅, 데이터 가져오기 및 기타 일반적인 사용 패턴에 사용할 도구를 선택해야 합니다. 이미 존재하는 프레임워크를 사용하는 대신 자신만의 프레임워크를 구축하는 것과 비슷합니다. 저희가 [권장하는 프레임워크](#full-stack-frameworks)에는 이러한 문제에 대한 기본 제공 솔루션이 있습니다. +======= +Starting from scratch gives you more flexibility, but does require that you make choices on which tools to use for routing, data fetching, and other common usage patterns. It's a lot like building your own framework, instead of using a framework that already exists. The [frameworks we recommend](#full-stack-frameworks) have built-in solutions for these problems. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 자신만의 솔루션을 구축하려면, [Vite](https://vite.dev/), [Parcel](https://parceljs.org/) 또는 [RSbuild](https://rsbuild.dev/)와 같은 빌드 도구로 시작할 수 있도록 하는 [처음부터 React 앱 만들기](/learn/build-a-react-app-from-scratch) 가이드를 참조하세요. diff --git a/src/content/learn/describing-the-ui.md b/src/content/learn/describing-the-ui.md index 5f24071b2..72449a44c 100644 --- a/src/content/learn/describing-the-ui.md +++ b/src/content/learn/describing-the-ui.md @@ -32,7 +32,7 @@ React 애플리케이션은 *컴포넌트*라고 불리는 독립된 UI 조각 function Profile() { return ( <img - src="https://i.imgur.com/MK3eW3As.jpg" + src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> ); @@ -97,7 +97,7 @@ export default function Gallery() { export default function Profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); @@ -130,7 +130,7 @@ export default function TodoList() { // This doesn't quite work! <h1>Hedy Lamarr's Todos</h1> <img - src="https://i.imgur.com/yXOvdOSs.jpg" + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" alt="Hedy Lamarr" class="photo" > @@ -159,7 +159,7 @@ export default function TodoList() { <> <h1>Hedy Lamarr's Todos</h1> <img - src="https://i.imgur.com/yXOvdOSs.jpg" + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" alt="Hedy Lamarr" className="photo" /> @@ -206,7 +206,7 @@ export default function TodoList() { <h1>{person.name}'s Todos</h1> <img className="avatar" - src="https://i.imgur.com/7vQD0fPs.jpg" + src="https://react.dev/images/docs/scientists/7vQD0fPs.jpg" alt="Gregorio Y. Zara" /> <ul> @@ -281,7 +281,7 @@ function Card({ children }) { ```js src/utils.js export function getImageUrl(person, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -434,7 +434,7 @@ export const people = [{ ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + 's.jpg' ); @@ -525,10 +525,16 @@ export default function TeaSet() { ## 트리로서의 UI {/*your-ui-as-a-tree*/} +<<<<<<< HEAD React는 컴포넌트와 모듈 간의 관계를 모델링하기 위해 트리를 사용합니다. React 렌더 트리는 컴포넌트 간의 부모-자식 관계를 나타냅니다. +======= +React uses trees to model the relationships between components and modules. + +A React render tree is a representation of the parent and child relationship between components. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Diagram name="generic_render_tree" height={250} width={500} alt="A tree graph with five nodes, with each node representing a component. The root node is located at the top the tree graph and is labelled 'Root Component'. It has two arrows extending down to two nodes labelled 'Component A' and 'Component C'. Each of the arrows is labelled with 'renders'. 'Component A' has a single 'renders' arrow to a node labelled 'Component B'. 'Component C' has a single 'renders' arrow to a node labelled 'Component D'."> @@ -538,7 +544,11 @@ React 렌더 트리 예시 트리의 상단에 위치한 컴포넌트와 루트 컴포넌트 근처의 컴포넌트를 최상위 컴포넌트라고 합니다. 자식 컴포넌트가 없는 컴포넌트를 리프 컴포넌트라고 합니다. 이 컴포넌트 분류는 앱의 데이터 흐름과 성능을 이해하는 데 유용합니다. +<<<<<<< HEAD 자바스크립트 모듈 간의 관계를 모델링하는 것은 앱을 이해하는데 유용한 또 다른 방법입니다. 이를 모듈 의존성 트리라고 정의합니다. +======= +Modelling the relationship between JavaScript modules is another useful way to understand your app. We refer to it as a module dependency tree. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Diagram name="generic_dependency_tree" height={250} width={500} alt="A tree graph with five nodes. Each node represents a JavaScript module. The top-most node is labelled 'RootModule.js'. It has three arrows extending to the nodes: 'ModuleA.js', 'ModuleB.js', and 'ModuleC.js'. Each arrow is labelled as 'imports'. 'ModuleC.js' node has a single 'imports' arrow that points to a node labelled 'ModuleD.js'."> @@ -546,7 +556,11 @@ React 렌더 트리 예시 </Diagram> +<<<<<<< HEAD 의존성 트리는 종종 빌드 도구에 의해 클라이언트가 다운로드하고 렌더링하는 데 필요한 모든 관련 자바스크립트 코드를 번들하는 데에 사용됩니다. 큰 번들 크기는 React 앱의 사용자 경험을 저하합니다. 모듈 의존성 트리를 이해하는 것은 이러한 문제를 디버깅하는 데 도움이 됩니다. +======= +A dependency tree is often used by build tools to bundle all the relevant JavaScript code for the client to download and render. A large bundle size regresses user experience for React apps. Understanding the module dependency tree is helpful to debug such issues. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <LearnMore path="/learn/understanding-your-ui-as-a-tree"> diff --git a/src/content/learn/editor-setup.md b/src/content/learn/editor-setup.md index 71b287166..1e4d47bdd 100644 --- a/src/content/learn/editor-setup.md +++ b/src/content/learn/editor-setup.md @@ -31,7 +31,11 @@ title: 에디터 설정하기 ### 린팅<sup>Linting</sup> {/*linting*/} +<<<<<<< HEAD 코드 린터<sup>Linter</sup>는 코드를 작성하는 동안 실시간으로 문제를 찾아, 빠른 문제 해결을 도와줍니다. 자바스크립트를 위한 오픈 소스 린터<sup>Linter</sup>인 [ESLint](https://eslint.org)를 가장 많이 사용합니다! +======= +Code linters find problems in your code as you write, helping you fix them early. [ESLint](https://eslint.org/) is a popular, open source linter for JavaScript. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a * [React를 위한 추천 설정과 함께 ESLint 설치하기](https://www.npmjs.com/package/eslint-config-react-app) (사전에 [Node.js](https://nodejs.org/ko/download/current/)를 설치해야 합니다.) * [VS Code의 ESLint를 공식 익스텐션과 통합하기](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) diff --git a/src/content/learn/escape-hatches.md b/src/content/learn/escape-hatches.md index 89eff6a73..50c5652f3 100644 --- a/src/content/learn/escape-hatches.md +++ b/src/content/learn/escape-hatches.md @@ -227,7 +227,11 @@ function Form() { } ``` +<<<<<<< HEAD 그러나 외부 시스템과 동기화하려면 Effect가 <em>필요</em>합니다. +======= +However, you *do* need Effects to synchronize with external systems. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <LearnMore path="/learn/you-might-not-need-an-effect"> diff --git a/src/content/learn/importing-and-exporting-components.md b/src/content/learn/importing-and-exporting-components.md index 6e232c982..fec12d705 100644 --- a/src/content/learn/importing-and-exporting-components.md +++ b/src/content/learn/importing-and-exporting-components.md @@ -28,7 +28,7 @@ title: 컴포넌트 import 및 export 하기 function Profile() { return ( <img - src="https://i.imgur.com/MK3eW3As.jpg" + src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> ); @@ -81,7 +81,7 @@ export default function App() { function Profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); @@ -194,7 +194,7 @@ export default function App() { export function Profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); @@ -282,7 +282,7 @@ export default function App() { export function Profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); @@ -350,7 +350,7 @@ export default function Gallery() { export function Profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); @@ -400,7 +400,7 @@ export default function Gallery() { export default function Profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); diff --git a/src/content/learn/index.md b/src/content/learn/index.md index eacf1f4fb..097f414a2 100644 --- a/src/content/learn/index.md +++ b/src/content/learn/index.md @@ -143,7 +143,7 @@ JSX 중괄호 안에 [문자열 연결](https://ko.javascript.info/operators#str ```js const user = { name: 'Hedy Lamarr', - imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg', + imageUrl: 'https://react.dev/images/docs/scientists/yXOvdOSs.jpg', imageSize: 90, }; diff --git a/src/content/learn/javascript-in-jsx-with-curly-braces.md b/src/content/learn/javascript-in-jsx-with-curly-braces.md index e948f59c5..7c1114bb7 100644 --- a/src/content/learn/javascript-in-jsx-with-curly-braces.md +++ b/src/content/learn/javascript-in-jsx-with-curly-braces.md @@ -28,7 +28,7 @@ export default function Avatar() { return ( <img className="avatar" - src="https://i.imgur.com/7vQD0fPs.jpg" + src="https://react.dev/images/docs/scientists/7vQD0fPs.jpg" alt="Gregorio Y. Zara" /> ); @@ -41,7 +41,11 @@ export default function Avatar() { </Sandpack> +<<<<<<< HEAD 여기에서는 `"https://i.imgur.com/7vQD0fPs.jpg"`와 `"Gregorio Y. Zara"`가 문자열로 전달되고 있습니다. +======= +Here, `"https://react.dev/images/docs/scientists/7vQD0fPs.jpg"` and `"Gregorio Y. Zara"` are being passed as strings. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 그러나 `src` 또는 `alt`를 동적으로 지정하려면 어떻게 해야 할까요? **`"`와`"`를 `{`와`}`로 바꿔 JavaScript의 값을 사용할 수 있습니다**. @@ -49,7 +53,7 @@ export default function Avatar() { ```js export default function Avatar() { - const avatar = 'https://i.imgur.com/7vQD0fPs.jpg'; + const avatar = 'https://react.dev/images/docs/scientists/7vQD0fPs.jpg'; const description = 'Gregorio Y. Zara'; return ( <img @@ -190,7 +194,7 @@ export default function TodoList() { <h1>{person.name}'s Todos</h1> <img className="avatar" - src="https://i.imgur.com/7vQD0fPs.jpg" + src="https://react.dev/images/docs/scientists/7vQD0fPs.jpg" alt="Gregorio Y. Zara" /> <ul> @@ -266,7 +270,7 @@ export default function TodoList() { <h1>{person}'s Todos</h1> <img className="avatar" - src="https://i.imgur.com/7vQD0fPs.jpg" + src="https://react.dev/images/docs/scientists/7vQD0fPs.jpg" alt="Gregorio Y. Zara" /> <ul> @@ -314,7 +318,7 @@ export default function TodoList() { <h1>{person.name}'s Todos</h1> <img className="avatar" - src="https://i.imgur.com/7vQD0fPs.jpg" + src="https://react.dev/images/docs/scientists/7vQD0fPs.jpg" alt="Gregorio Y. Zara" /> <ul> @@ -358,7 +362,7 @@ export default function TodoList() { <h1>{person.name}'s Todos</h1> <img className="avatar" - src="https://i.imgur.com/7vQD0fPs.jpg" + src="https://react.dev/images/docs/scientists/7vQD0fPs.jpg" alt="Gregorio Y. Zara" /> <ul> @@ -388,7 +392,7 @@ body > div > div { padding: 20px; } ```js const person = { name: 'Gregorio Y. Zara', - imageUrl: "https://i.imgur.com/7vQD0fPs.jpg", + imageUrl: "https://react.dev/images/docs/scientists/7vQD0fPs.jpg", theme: { backgroundColor: 'black', color: 'pink' @@ -428,7 +432,11 @@ body > div > div { padding: 20px; } 아래 객체에서 전체 이미지 URL은 기본 URL, `imageId`, `imageSize` 및 파일 확장자 네 부분으로 나누어져 있습니다. +<<<<<<< HEAD 이미지 URL은 기본 URL (항상 `'https://i.imgur.com/'`), `imageId` (`'7vQD0fP'`), `imageSize` (`'s'`) 및 파일 확장자 (항상 `'.jpg'`)와 같은 어트리뷰트를 결합합니다. 그러나 `<img>` 태그가 `src`를 지정하는 방식에 문제가 있습니다. +======= +We want the image URL to combine these attributes together: base URL (always `'https://react.dev/images/docs/scientists/'`), `imageId` (`'7vQD0fP'`), `imageSize` (`'s'`), and file extension (always `'.jpg'`). However, something is wrong with how the `<img>` tag specifies its `src`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 어떻게 고칠 수 있을까요? @@ -436,7 +444,7 @@ body > div > div { padding: 20px; } ```js -const baseUrl = 'https://i.imgur.com/'; +const baseUrl = 'https://react.dev/images/docs/scientists/'; const person = { name: 'Gregorio Y. Zara', imageId: '7vQD0fP', @@ -487,7 +495,7 @@ body > div > div { padding: 20px; } <Sandpack> ```js -const baseUrl = 'https://i.imgur.com/'; +const baseUrl = 'https://react.dev/images/docs/scientists/'; const person = { name: 'Gregorio Y. Zara', imageId: '7vQD0fP', @@ -564,7 +572,7 @@ export default function TodoList() { ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + person.imageSize + '.jpg' diff --git a/src/content/learn/keeping-components-pure.md b/src/content/learn/keeping-components-pure.md index 01af2885d..3c23c43a7 100644 --- a/src/content/learn/keeping-components-pure.md +++ b/src/content/learn/keeping-components-pure.md @@ -27,6 +27,7 @@ title: 컴포넌트를 순수하게 유지하기 이 수학 공식을 생각해보세요. <Math><MathI>y</MathI> = 2<MathI>x</MathI></Math>. +<<<<<<< HEAD 만약 <Math><MathI>x</MathI> = 2</Math>이라면 항상 <Math><MathI>y</MathI> = 4</Math>입니다. 만약 <Math><MathI>x</MathI> = 3</Math>이라면 항상 <Math><MathI>y</MathI> = 6</Math>입니다. @@ -34,6 +35,15 @@ title: 컴포넌트를 순수하게 유지하기 만약 <Math><MathI>x</MathI> = 3</Math>이라면, 그날의 시간이나 주식 시장의 상태에 따라 <MathI>y</MathI>가 갑자기 <Math>9</Math>가 되거나 <Math>–1</Math>이 되거나 <Math>2.5</Math>가 되는 일은 일어나지 않습니다. 만약 <Math><MathI>y</MathI> = 2<MathI>x</MathI></Math> 그리고 <Math><MathI>x</MathI> = 3</Math>이라면, <MathI>y</MathI>는 _항상_ <Math>6</Math>이 될 것입니다. +======= +If <Math><MathI>x</MathI> = 2</Math> then <Math><MathI>y</MathI> = 4</Math>. Always. + +If <Math><MathI>x</MathI> = 3</Math> then <Math><MathI>y</MathI> = 6</Math>. Always. + +If <Math><MathI>x</MathI> = 3</Math>, <MathI>y</MathI> won't sometimes be <Math>9</Math> or <Math>–1</Math> or <Math>2.5</Math> depending on the time of day or the state of the stock market. + +If <Math><MathI>y</MathI> = 2<MathI>x</MathI></Math> and <Math><MathI>x</MathI> = 3</Math>, <MathI>y</MathI> will _always_ be <Math>6</Math>. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 위 내용들을 자바스크립트 함수로 만든다면 아래와 같습니다. @@ -75,11 +85,19 @@ export default function App() { </Sandpack> +<<<<<<< HEAD `Recipe`에 `drinkers={2}`를 넘기면 항상 `2 cups of water`를 포함한 JSX 반환합니다. +======= +When you pass `drinkers={2}` to `Recipe`, it will return JSX containing `2 cups of water`. Always. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a `drinkers={4}`를 넘기면 항상 `4 cups of water`를 포함한 JSX를 반환합니다. +<<<<<<< HEAD 수학 공식처럼 말입니다. +======= +Just like a math formula. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 컴포넌트를 마치 레시피라고 생각할 수도 있습니다. 레시피를 그대로 따르고 요리 중 새로운 재료를 추가하지 않으면 매번 동일한 요리를 만들 수 있습니다. 여기서 "요리"는 컴포넌트가 React에 전달하여 [렌더링](/learn/render-and-commit)하도록 하는 JSX입니다. @@ -215,6 +233,7 @@ React에서, **사이드 이펙트는 보통 [이벤트 핸들러](/learn/respon <Recap> +<<<<<<< HEAD * 컴포넌트는 순수해야만 합니다. 이것은 두 가지를 의미합니다. * **자신의 일에만 집중합니다.** 렌더링 전에 존재했던 객체나 변수를 변경하지 않아야 합니다. * **같은 입력, 같은 출력.** 입력이 같을 경우, 컴포넌트는 항상 같은 JSX를 반환해야 합니다. @@ -225,6 +244,20 @@ React에서, **사이드 이펙트는 보통 [이벤트 핸들러](/learn/respon </Recap> +======= +* A component must be pure, meaning: + * **It minds its own business.** It should not change any objects or variables that existed before rendering. + * **Same inputs, same output.** Given the same inputs, a component should always return the same JSX. +* Rendering can happen at any time, so components should not depend on each others' rendering sequence. +* You should not mutate any of the inputs that your components use for rendering. That includes props, state, and context. To update the screen, ["set" state](/learn/state-a-components-memory) instead of mutating preexisting objects. +* Strive to express your component's logic in the JSX you return. When you need to "change things", you'll usually want to do it in an event handler. As a last resort, you can `useEffect`. +* Writing pure functions takes a bit of practice, but it unlocks the power of React's paradigm. + +</Recap> + + + +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Challenges> #### 고장난 시계 고치기 {/*fix-a-broken-clock*/} @@ -449,7 +482,7 @@ export default function App() { ```js src/utils.js hidden export function getImageUrl(person, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -547,7 +580,7 @@ export default function App() { ```js src/utils.js hidden export function getImageUrl(person, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' diff --git a/src/content/learn/lifecycle-of-reactive-effects.md b/src/content/learn/lifecycle-of-reactive-effects.md index 3572c280f..75c40a4f8 100644 --- a/src/content/learn/lifecycle-of-reactive-effects.md +++ b/src/content/learn/lifecycle-of-reactive-effects.md @@ -293,7 +293,11 @@ button { margin-left: 10px; } ```js {1,3,8} function ChatRoom({ roomId }) { // roomId prop은 시간이 지남에 따라 변경될 수 있습니다. useEffect(() => { +<<<<<<< HEAD const connection = createConnection(serverUrl, roomId); // 이 effect는 roomId를 읽습니다. +======= + const connection = createConnection(serverUrl, roomId); // This Effect reads roomId +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a connection.connect(); return () => { connection.disconnect(); diff --git a/src/content/learn/passing-data-deeply-with-context.md b/src/content/learn/passing-data-deeply-with-context.md index 8241a12c6..0bd25a258 100644 --- a/src/content/learn/passing-data-deeply-with-context.md +++ b/src/content/learn/passing-data-deeply-with-context.md @@ -853,10 +853,19 @@ Context는 사용하기에 꽤 유혹적입니다. 그러나 이는 또한 남 ## Context 사용 예시 {/*use-cases-for-context*/} +<<<<<<< HEAD - **테마 지정하기:** 사용자가 모양을 변경할 수 있는 애플리케이션의 경우에 (e.g. 다크 모드) context provider를 앱 최상단에 두고 시각적으로 조정이 필요한 컴포넌트에서 context를 사용할 수 있습니다. - **현재 계정:** 로그인한 사용자를 알아야 하는 컴포넌트가 많을 수 있습니다. Context에 놓으면 트리 어디에서나 편하게 알아낼 수 있습니다. 일부 애플리케이션에서는 동시에 여러 계정을 운영할 수도 있습니다. (e.g. 다른 사용자로 댓글을 남기는 경우.) 이런 경우에는 UI의 일부를 서로 다른 현재 계정 값을 가진 provider로 감싸 주는 것이 편리합니다. - **라우팅:** 대부분의 라우팅 솔루션은 현재 경로를 유지하기 위해 내부적으로 context를 사용합니다. 이것이 모든 링크의 활성화 여부를 "알 수 있는" 방법입니다. 라우터를 만든다면 같은 방식으로 하고 싶을 것입니다. - **상태 관리:** 애플리케이션이 커지면 결국 앱 상단에 수많은 state가 생기게 됩니다. 아래 멀리 떨어진 많은 컴포넌트가 그 값을 변경하고 싶어할 수 있습니다. 흔히 [reducer를 context와 함께 사용하는 것](/learn/scaling-up-with-reducer-and-context)은 복잡한 state를 관리하고 번거로운 작업 없이 멀리 있는 컴포넌트까지 값을 전달하는 방법입니다. +======= +* **Theming:** If your app lets the user change its appearance (e.g. dark mode), you can put a context provider at the top of your app, and use that context in components that need to adjust their visual look. +* **Current account:** Many components might need to know the currently logged in user. Putting it in context makes it convenient to read it anywhere in the tree. Some apps also let you operate multiple accounts at the same time (e.g. to leave a comment as a different user). In those cases, it can be convenient to wrap a part of the UI into a nested provider with a different current account value. +* **Routing:** Most routing solutions use context internally to hold the current route. This is how every link "knows" whether it's active or not. If you build your own router, you might want to do it too. +* **Managing state:** As your app grows, you might end up with a lot of state closer to the top of your app. Many distant components below may want to change it. It is common to [use a reducer together with context](/learn/scaling-up-with-reducer-and-context) to manage complex state and pass it down to distant components without too much hassle. + +Context is not limited to static values. If you pass a different value on the next render, React will update all the components reading it below! This is why context is often used in combination with state. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a Context는 정적인 값으로 제한되지 않습니다. 다음 렌더링 시 다른 값을 준다면 React는 아래의 모든 컴포넌트에서 그 값을 갱신합니다. 이것은 context와 state가 자주 조합되는 이유입니다. @@ -998,7 +1007,7 @@ export const places = [{ ```js src/utils.js export function getImageUrl(place) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + place.imageId + 'l.jpg' ); @@ -1137,7 +1146,7 @@ export const places = [{ ```js src/utils.js export function getImageUrl(place) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + place.imageId + 'l.jpg' ); diff --git a/src/content/learn/passing-props-to-a-component.md b/src/content/learn/passing-props-to-a-component.md index 5ae3ac179..b07ed8027 100644 --- a/src/content/learn/passing-props-to-a-component.md +++ b/src/content/learn/passing-props-to-a-component.md @@ -29,7 +29,7 @@ function Avatar() { return ( <img className="avatar" - src="https://i.imgur.com/1bX5QH6.jpg" + src="https://react.dev/images/docs/scientists/1bX5QH6.jpg" alt="Lin Lanying" width={100} height={100} @@ -153,7 +153,7 @@ export default function Profile() { ```js src/utils.js export function getImageUrl(person, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -323,7 +323,7 @@ export default function Avatar({ person, size }) { ```js src/utils.js export function getImageUrl(person, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -503,7 +503,7 @@ export default function Gallery() { ```js src/utils.js export function getImageUrl(imageId, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + imageId + size + '.jpg' @@ -611,7 +611,7 @@ export default function Gallery() { ```js src/utils.js export function getImageUrl(imageId, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + imageId + size + '.jpg' @@ -708,7 +708,7 @@ export default function Gallery() { ```js src/utils.js export function getImageUrl(person, size = 's') { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -774,7 +774,7 @@ export default function Profile() { ```js src/utils.js export function getImageUrl(person, size) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -838,7 +838,7 @@ export default function Profile() { ```js src/utils.js export function getImageUrl(person, size) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -909,7 +909,7 @@ export default function Profile() { ```js src/utils.js export function getImageUrl(person, size) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + size + '.jpg' @@ -942,7 +942,7 @@ export default function Profile() { <h1>Photo</h1> <img className="avatar" - src="https://i.imgur.com/OKS67lhm.jpg" + src="https://react.dev/images/docs/scientists/OKS67lhm.jpg" alt="Aklilu Lemma" width={70} height={70} @@ -1015,7 +1015,7 @@ export default function Profile() { <h1>Photo</h1> <img className="avatar" - src="https://i.imgur.com/OKS67lhm.jpg" + src="https://react.dev/images/docs/scientists/OKS67lhm.jpg" alt="Aklilu Lemma" width={100} height={100} @@ -1077,7 +1077,7 @@ export default function Profile() { <Card title="Photo"> <img className="avatar" - src="https://i.imgur.com/OKS67lhm.jpg" + src="https://react.dev/images/docs/scientists/OKS67lhm.jpg" alt="Aklilu Lemma" width={100} height={100} diff --git a/src/content/learn/preserving-and-resetting-state.md b/src/content/learn/preserving-and-resetting-state.md index e5b4b5d0d..81720cdeb 100644 --- a/src/content/learn/preserving-and-resetting-state.md +++ b/src/content/learn/preserving-and-resetting-state.md @@ -86,7 +86,11 @@ label { </Sandpack> +<<<<<<< HEAD 카운터가 다음과 같이 트리 구조로 보입니다. +======= +Here's how these look as a tree: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <DiagramGroup> @@ -1883,25 +1887,25 @@ export default function Gallery() { let images = [{ place: 'Penang, Malaysia', - src: 'https://i.imgur.com/FJeJR8M.jpg' + src: 'https://react.dev/images/docs/scientists/FJeJR8M.jpg' }, { place: 'Lisbon, Portugal', - src: 'https://i.imgur.com/dB2LRbj.jpg' + src: 'https://react.dev/images/docs/scientists/dB2LRbj.jpg' }, { place: 'Bilbao, Spain', - src: 'https://i.imgur.com/z08o2TS.jpg' + src: 'https://react.dev/images/docs/scientists/z08o2TS.jpg' }, { place: 'Valparaíso, Chile', - src: 'https://i.imgur.com/Y3utgTi.jpg' + src: 'https://react.dev/images/docs/scientists/Y3utgTi.jpg' }, { place: 'Schwyz, Switzerland', - src: 'https://i.imgur.com/JBbMpWY.jpg' + src: 'https://react.dev/images/docs/scientists/JBbMpWY.jpg' }, { place: 'Prague, Czechia', - src: 'https://i.imgur.com/QwUKKmF.jpg' + src: 'https://react.dev/images/docs/scientists/QwUKKmF.jpg' }, { place: 'Ljubljana, Slovenia', - src: 'https://i.imgur.com/3aIiwfm.jpg' + src: 'https://react.dev/images/docs/scientists/3aIiwfm.jpg' }]; ``` @@ -1951,25 +1955,25 @@ export default function Gallery() { let images = [{ place: 'Penang, Malaysia', - src: 'https://i.imgur.com/FJeJR8M.jpg' + src: 'https://react.dev/images/docs/scientists/FJeJR8M.jpg' }, { place: 'Lisbon, Portugal', - src: 'https://i.imgur.com/dB2LRbj.jpg' + src: 'https://react.dev/images/docs/scientists/dB2LRbj.jpg' }, { place: 'Bilbao, Spain', - src: 'https://i.imgur.com/z08o2TS.jpg' + src: 'https://react.dev/images/docs/scientists/z08o2TS.jpg' }, { place: 'Valparaíso, Chile', - src: 'https://i.imgur.com/Y3utgTi.jpg' + src: 'https://react.dev/images/docs/scientists/Y3utgTi.jpg' }, { place: 'Schwyz, Switzerland', - src: 'https://i.imgur.com/JBbMpWY.jpg' + src: 'https://react.dev/images/docs/scientists/JBbMpWY.jpg' }, { place: 'Prague, Czechia', - src: 'https://i.imgur.com/QwUKKmF.jpg' + src: 'https://react.dev/images/docs/scientists/QwUKKmF.jpg' }, { place: 'Ljubljana, Slovenia', - src: 'https://i.imgur.com/3aIiwfm.jpg' + src: 'https://react.dev/images/docs/scientists/3aIiwfm.jpg' }]; ``` diff --git a/src/content/learn/queueing-a-series-of-state-updates.md b/src/content/learn/queueing-a-series-of-state-updates.md index 966530a63..bba59b426 100644 --- a/src/content/learn/queueing-a-series-of-state-updates.md +++ b/src/content/learn/queueing-a-series-of-state-updates.md @@ -178,7 +178,11 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; } | "replace with `5`" | `0` (unused) | `5` | | `n => n + 1` | `5` | `5 + 1 = 6` | +<<<<<<< HEAD React는 `6`을 최종 결과로 저장하고 `useState`에서 반환합니다. +======= +React stores `6` as the final result and returns it from `useState`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Note> diff --git a/src/content/learn/reacting-to-input-with-state.md b/src/content/learn/reacting-to-input-with-state.md index 662fab0d3..902c3c09b 100644 --- a/src/content/learn/reacting-to-input-with-state.md +++ b/src/content/learn/reacting-to-input-with-state.md @@ -514,7 +514,7 @@ export default function Picture() { <img className="picture" alt="Rainbow houses in Kampung Pelangi, Indonesia" - src="https://i.imgur.com/5qwVYb1.jpeg" + src="https://react.dev/images/docs/scientists/5qwVYb1.jpeg" /> </div> ); @@ -590,7 +590,7 @@ export default function Picture() { }} className={pictureClassName} alt="Rainbow houses in Kampung Pelangi, Indonesia" - src="https://i.imgur.com/5qwVYb1.jpeg" + src="https://react.dev/images/docs/scientists/5qwVYb1.jpeg" /> </div> ); @@ -645,7 +645,7 @@ export default function Picture() { <img className="picture picture--active" alt="Rainbow houses in Kampung Pelangi, Indonesia" - src="https://i.imgur.com/5qwVYb1.jpeg" + src="https://react.dev/images/docs/scientists/5qwVYb1.jpeg" onClick={e => e.stopPropagation()} /> </div> @@ -656,7 +656,7 @@ export default function Picture() { <img className="picture" alt="Rainbow houses in Kampung Pelangi, Indonesia" - src="https://i.imgur.com/5qwVYb1.jpeg" + src="https://react.dev/images/docs/scientists/5qwVYb1.jpeg" onClick={() => setIsActive(true)} /> </div> diff --git a/src/content/learn/referencing-values-with-refs.md b/src/content/learn/referencing-values-with-refs.md index 4801840a9..083b268f6 100644 --- a/src/content/learn/referencing-values-with-refs.md +++ b/src/content/learn/referencing-values-with-refs.md @@ -35,7 +35,11 @@ const ref = useRef(0); ```js { +<<<<<<< HEAD current: 0 // useRef에 전달한 값 +======= + current: 0 // The value you passed to useRef +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a } ``` diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md index 148c1fadd..4cdedbaf1 100644 --- a/src/content/learn/removing-effect-dependencies.md +++ b/src/content/learn/removing-effect-dependencies.md @@ -879,7 +879,11 @@ const options2 = { serverUrl: 'https://localhost:1234', roomId: 'music' }; console.log(Object.is(options1, options2)); // false ``` +<<<<<<< HEAD **객체 및 함수 의존성으로 인해 Effect가 필요 이상으로 자주 재동기화될 수 있습니다.** +======= +**Object and function dependencies can make your Effect re-synchronize more often than you need.** +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 그렇기 때문에 가능하면 객체와 함수를 Effect의 의존성으로 사용하지 않는 것이 좋습니다. 대신 컴포넌트 외부나 Effect 내부로 이동하거나 원시 값을 추출해 보세요. diff --git a/src/content/learn/render-and-commit.md b/src/content/learn/render-and-commit.md index b4f5bfaaa..1f9dd5c53 100644 --- a/src/content/learn/render-and-commit.md +++ b/src/content/learn/render-and-commit.md @@ -54,7 +54,7 @@ root.render(<Image />); export default function Image() { return ( <img - src="https://i.imgur.com/ZF6s192.jpg" + src="https://react.dev/images/docs/scientists/ZF6s192.jpg" alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals" /> ); @@ -103,7 +103,7 @@ export default function Gallery() { function Image() { return ( <img - src="https://i.imgur.com/ZF6s192.jpg" + src="https://react.dev/images/docs/scientists/ZF6s192.jpg" alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals" /> ); @@ -124,8 +124,13 @@ img { margin: 0 10px 10px 0; } </Sandpack> +<<<<<<< HEAD * **초기 렌더링 하는 동안** React는 `<section>`, `<h1>` 그리고 3개의 `<img>` 태그에 대한 [DOM 노드를 생성](https://developer.mozilla.org/docs/Web/API/Document/createElement)합니다. * **리렌더링하는 동안** React는 이전 렌더링 이후 변경된 속성을 계산합니다. 다음 단계인 커밋 단계까지는 해당 정보로 아무런 작업도 수행하지 않습니다. +======= +* **During the initial render,** React will [create the DOM nodes](https://developer.mozilla.org/docs/Web/API/Document/createElement) for `<section>`, `<h1>`, and three `<img>` tags. +* **During a re-render,** React will calculate which of their properties, if any, have changed since the previous render. It won't do anything with that information until the next step, the commit phase. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Pitfall> diff --git a/src/content/learn/rendering-lists.md b/src/content/learn/rendering-lists.md index 1ba2aaabe..c80e8833e 100644 --- a/src/content/learn/rendering-lists.md +++ b/src/content/learn/rendering-lists.md @@ -223,7 +223,7 @@ export const people = [{ ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + 's.jpg' ); @@ -353,7 +353,7 @@ export const people = [{ ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + 's.jpg' ); @@ -514,7 +514,7 @@ export const people = [{ ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + 's.jpg' ); @@ -629,7 +629,7 @@ export const people = [{ ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + 's.jpg' ); @@ -743,7 +743,7 @@ export const people = [{ ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + 's.jpg' ); @@ -861,7 +861,7 @@ export const people = [{ ```js src/utils.js export function getImageUrl(person) { return ( - 'https://i.imgur.com/' + + 'https://react.dev/images/docs/scientists/' + person.imageId + 's.jpg' ); diff --git a/src/content/learn/responding-to-events.md b/src/content/learn/responding-to-events.md index da9f93c7f..7269b68fb 100644 --- a/src/content/learn/responding-to-events.md +++ b/src/content/learn/responding-to-events.md @@ -169,7 +169,11 @@ button { margin-right: 10px; } ### 이벤트 핸들러를 Prop으로 전달하기 {/*passing-event-handlers-as-props*/} +<<<<<<< HEAD 종종 부모 컴포넌트로 자식의 이벤트 핸들러를 지정하기를 원할 수 있습니다. 버튼의 경우를 고려해봅시다. `Button` 컴포넌트를 사용하는 위치에 따라 다른 기능을 수행하도록 만들고자 할 때가 있을 것입니다. 한 버튼은 영화를 재생하고 다른 버튼은 이미지를 업로드하도록 말이죠. +======= +Often you'll want the parent component to specify a child's event handler. Consider buttons: depending on where you're using a `Button` component, you might want to execute a different function—perhaps one plays a movie and another uploads an image. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 이러한 기능을 위해서 컴포넌트가 그 부모 컴포넌트로부터 받은 prop을 이벤트 핸들러로 다음과 같이 전달합니다. @@ -312,11 +316,19 @@ button { margin-right: 10px; } </Sandpack> +<<<<<<< HEAD `App` 컴포넌트는 `Toolbar`가 `onPlayMovie` 또는 `onUploadImage`를 가지고 *무엇*을 할 것인지 알 필요가 없음에 유의하세요. 이 `Toolbar` 구현의 특별한 부분입니다. 지금 `Toolbar`는 위 요소들을 `Button`의 `onClick` 핸들러 요소로 내려보내지만, 추후에는 키보드 바로가기 키 입력을 통해 이들을 활성화할 수도 있을 것입니다. `onPlayMovie`와 같이 prop 이름을 애플리케이션별 상호작용에 기반하여 명명한다면 나중에 어떻게 이를 이용하게 될지에 대한 유연성을 제공할 것입니다. <Note> 이벤트 핸들러에 적절한 HTML 태그를 사용하고 있는지 확인하세요. 예를 들어 클릭을 처리하기 위해서는 `<div onClick={handleClick}>` 대신 [`<button onClick={handleClick}>`](https://developer.mozilla.org/ko/docs/Web/HTML/Element/button)을 사용하세요. 실제 브라우저에서 `<button>`은 키보드 내비게이션과 같은 빌트인 브라우저 동작을 활성화 합니다. 만일 버튼의 기본 브라우저 스타일링이 싫어서 링크나 다른 UI 요소처럼 보이도록 하고 싶다면 CSS를 통해 그 목적을 이룰 수 있습니다. [접근성을 위한 마크업 작성법에 대해 더 알아보세요.](https://developer.mozilla.org/ko/docs/Learn/Accessibility/HTML) +======= +Notice how the `App` component does not need to know *what* `Toolbar` will do with `onPlayMovie` or `onUploadImage`. That's an implementation detail of the `Toolbar`. Here, `Toolbar` passes them down as `onClick` handlers to its `Button`s, but it could later also trigger them on a keyboard shortcut. Naming props after app-specific interactions like `onPlayMovie` gives you the flexibility to change how they're used later. + +<Note> + +Make sure that you use the appropriate HTML tags for your event handlers. For example, to handle clicks, use [`<button onClick={handleClick}>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) instead of `<div onClick={handleClick}>`. Using a real browser `<button>` enables built-in browser behaviors like keyboard navigation. If you don't like the default browser styling of a button and want to make it look more like a link or a different UI element, you can achieve it with CSS. [Learn more about writing accessible markup.](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML) +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Note> @@ -411,12 +423,21 @@ button { margin: 5px; } 버튼을 클릭하면 다음과 같은 절차가 진행됩니다. +<<<<<<< HEAD 1. React가 `<button>`에 전달된 `onClick` 핸들러를 호출합니다. 2. `Button`에 정의된 해당 핸들러는 다음을 수행합니다. * `e.stopPropagation()`을 호출하여 이벤트가 더 이상 bubbling 되지 않도록 방지합니다. * `Toolbar` 컴포넌트가 전달해 준 `onClick` 함수를 호출합니다. 3. `Toolbar` 컴포넌트에서 정의된 위 함수가 버튼의 alert를 표시합니다. 4. 전파가 중단되었으므로 부모인 `<div>`의 `onClick`은 *실행되지 않습니다*. +======= +1. React calls the `onClick` handler passed to `<button>`. +2. That handler, defined in `Button`, does the following: + * Calls `e.stopPropagation()`, preventing the event from bubbling further. + * Calls the `onClick` function, which is a prop passed from the `Toolbar` component. +3. That function, defined in the `Toolbar` component, displays the button's own alert. +4. Since the propagation was stopped, the parent `<div>`'s `onClick` handler does *not* run. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a `e.stopPropagation()`의 결과, 버튼을 클릭하는 것은 이제 `<button>`과 그 부모인 툴바의 `<div>`가 보내는 두 개의 alert를 표시하지 않고 단 하나의 `<button>` alert 만을 표시합니다. 버튼을 클릭하는 것은 그 주변의 툴바 부분을 클릭하는 것과 같지 않기에 이 UI 상에서는 전파를 멈추는 것이 합리적일 것입니다. @@ -433,11 +454,19 @@ button { margin: 5px; } </div> ``` +<<<<<<< HEAD 각각의 이벤트는 세 단계를 거쳐 전파됩니다. 1. 아래로 전달되면서 만나는 모든 `onClickCapture` 핸들러를 호출합니다. 2. 클릭된 요소의 `onClick` 핸들러를 실행합니다. 3. 위로 전달되면서 만나는 모든 `onClick` 핸들러를 호출합니다. +======= +Each event propagates in three phases: + +1. It travels down, calling all `onClickCapture` handlers. +2. It runs the clicked element's `onClick` handler. +3. It travels upwards, calling all `onClick` handlers. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 이벤트 캡처는 라우터나 분석을 위한 코드에 유용할 수 있지만 일반 애플리케이션 코드에서는 사용하지 않을 가능성이 높습니다. diff --git a/src/content/learn/sharing-state-between-components.md b/src/content/learn/sharing-state-between-components.md index 424806622..6bebb6986 100644 --- a/src/content/learn/sharing-state-between-components.md +++ b/src/content/learn/sharing-state-between-components.md @@ -323,7 +323,11 @@ React 애플리케이션에서 많은 컴포넌트는 자체 state를 가집니 #### 동기화된 입력 {/*synced-inputs*/} +<<<<<<< HEAD 아래 두 입력은 독립적입니다. 두 입력의 동기화 상태를 유지하세요. 한 입력을 수정하면 다른 입력도 같은 문구로 변경되어야 하며 반대 경우도 동일합니다. +======= +These two inputs are independent. Make them stay in sync: editing one input should update the other input with the same text, and vice versa. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Hint> @@ -569,12 +573,23 @@ function SearchBar({ query, onChange }) { function List({ items }) { return ( <table> +<<<<<<< HEAD {items.map(food => ( <tr key={food.id}> <td>{food.name}</td> <td>{food.description}</td> </tr> ))} +======= + <tbody> + {items.map(food => ( + <tr key={food.id}> + <td>{food.name}</td> + <td>{food.description}</td> + </tr> + ))} + </tbody> +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </table> ); } diff --git a/src/content/learn/state-a-components-memory.md b/src/content/learn/state-a-components-memory.md index c93da4778..3837ed7b1 100644 --- a/src/content/learn/state-a-components-memory.md +++ b/src/content/learn/state-a-components-memory.md @@ -63,73 +63,77 @@ export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', +<<<<<<< HEAD url: 'https://i.imgur.com/Mx7dA2Y.jpg', +======= + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; ``` @@ -243,73 +247,77 @@ export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', +<<<<<<< HEAD url: 'https://i.imgur.com/Mx7dA2Y.jpg', +======= + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; ``` @@ -361,7 +369,11 @@ const [index, setIndex] = useState(0); </Note> +<<<<<<< HEAD `useState`의 유일한 인수는 state 변수의 **초깃값**입니다. 이 예시에서 `index`의 초깃값은 `useState(0)`에 의해 `0`으로 설정됩니다. +======= +The only argument to `useState` is the **initial value** of your state variable. In this example, the `index`'s initial value is set to `0` with `useState(0)`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 컴포넌트가 렌더링될 때마다, `useState`는 다음 두 개의 값을 포함하는 배열을 제공합니다. @@ -432,73 +444,77 @@ export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', +<<<<<<< HEAD url: 'https://i.imgur.com/Mx7dA2Y.jpg', +======= + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; ``` @@ -628,73 +644,77 @@ let sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', +<<<<<<< HEAD url: 'https://i.imgur.com/Mx7dA2Y.jpg', +======= + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; @@ -796,73 +816,77 @@ export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', +<<<<<<< HEAD url: 'https://i.imgur.com/Mx7dA2Y.jpg', +======= + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; ``` @@ -967,73 +991,77 @@ export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', +<<<<<<< HEAD url: 'https://i.imgur.com/Mx7dA2Y.jpg', +======= + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; ``` @@ -1129,73 +1157,77 @@ export const sculptureList = [{ name: 'Homenaje a la Neurocirugía', artist: 'Marta Colvin Andrade', description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.', +<<<<<<< HEAD url: 'https://i.imgur.com/Mx7dA2Y.jpg', +======= + url: 'https://react.dev/images/docs/scientists/Mx7dA2Y.jpg', +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.' }, { name: 'Floralis Genérica', artist: 'Eduardo Catalano', description: 'This enormous (75 ft. or 23m) silver flower is located in Buenos Aires. It is designed to move, closing its petals in the evening or when strong winds blow and opening them in the morning.', - url: 'https://i.imgur.com/ZF6s192m.jpg', + url: 'https://react.dev/images/docs/scientists/ZF6s192m.jpg', alt: 'A gigantic metallic flower sculpture with reflective mirror-like petals and strong stamens.' }, { name: 'Eternal Presence', artist: 'John Woodrow Wilson', description: 'Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as "a symbolic Black presence infused with a sense of universal humanity."', - url: 'https://i.imgur.com/aTtVpES.jpg', + url: 'https://react.dev/images/docs/scientists/aTtVpES.jpg', alt: 'The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity.' }, { name: 'Moai', artist: 'Unknown Artist', description: 'Located on the Easter Island, there are 1,000 moai, or extant monumental statues, created by the early Rapa Nui people, which some believe represented deified ancestors.', - url: 'https://i.imgur.com/RCwLEoQm.jpg', + url: 'https://react.dev/images/docs/scientists/RCwLEoQm.jpg', alt: 'Three monumental stone busts with the heads that are disproportionately large with somber faces.' }, { name: 'Blue Nana', artist: 'Niki de Saint Phalle', description: 'The Nanas are triumphant creatures, symbols of femininity and maternity. Initially, Saint Phalle used fabric and found objects for the Nanas, and later on introduced polyester to achieve a more vibrant effect.', - url: 'https://i.imgur.com/Sd1AgUOm.jpg', + url: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', alt: 'A large mosaic sculpture of a whimsical dancing female figure in a colorful costume emanating joy.' }, { name: 'Ultimate Form', artist: 'Barbara Hepworth', description: 'This abstract bronze sculpture is a part of The Family of Man series located at Yorkshire Sculpture Park. Hepworth chose not to create literal representations of the world but developed abstract forms inspired by people and landscapes.', - url: 'https://i.imgur.com/2heNQDcm.jpg', + url: 'https://react.dev/images/docs/scientists/2heNQDcm.jpg', alt: 'A tall sculpture made of three elements stacked on each other reminding of a human figure.' }, { name: 'Cavaliere', artist: 'Lamidi Olonade Fakeye', description: "Descended from four generations of woodcarvers, Fakeye's work blended traditional and contemporary Yoruba themes.", - url: 'https://i.imgur.com/wIdGuZwm.png', + url: 'https://react.dev/images/docs/scientists/wIdGuZwm.png', alt: 'An intricate wood sculpture of a warrior with a focused face on a horse adorned with patterns.' }, { name: 'Big Bellies', artist: 'Alina Szapocznikow', description: "Szapocznikow is known for her sculptures of the fragmented body as a metaphor for the fragility and impermanence of youth and beauty. This sculpture depicts two very realistic large bellies stacked on top of each other, each around five feet (1,5m) tall.", - url: 'https://i.imgur.com/AlHTAdDm.jpg', + url: 'https://react.dev/images/docs/scientists/AlHTAdDm.jpg', alt: 'The sculpture reminds a cascade of folds, quite different from bellies in classical sculptures.' }, { name: 'Terracotta Army', artist: 'Unknown Artist', description: 'The Terracotta Army is a collection of terracotta sculptures depicting the armies of Qin Shi Huang, the first Emperor of China. The army consisted of more than 8,000 soldiers, 130 chariots with 520 horses, and 150 cavalry horses.', - url: 'https://i.imgur.com/HMFmH6m.jpg', + url: 'https://react.dev/images/docs/scientists/HMFmH6m.jpg', alt: '12 terracotta sculptures of solemn warriors, each with a unique facial expression and armor.' }, { name: 'Lunar Landscape', artist: 'Louise Nevelson', description: 'Nevelson was known for scavenging objects from New York City debris, which she would later assemble into monumental constructions. In this one, she used disparate parts like a bedpost, juggling pin, and seat fragment, nailing and gluing them into boxes that reflect the influence of Cubism’s geometric abstraction of space and form.', - url: 'https://i.imgur.com/rN7hY6om.jpg', + url: 'https://react.dev/images/docs/scientists/rN7hY6om.jpg', alt: 'A black matte sculpture where the individual elements are initially indistinguishable.' }, { name: 'Aureole', artist: 'Ranjani Shettar', description: 'Shettar merges the traditional and the modern, the natural and the industrial. Her art focuses on the relationship between man and nature. Her work was described as compelling both abstractly and figuratively, gravity defying, and a "fine synthesis of unlikely materials."', - url: 'https://i.imgur.com/okTpbHhm.jpg', + url: 'https://react.dev/images/docs/scientists/okTpbHhm.jpg', alt: 'A pale wire-like sculpture mounted on concrete wall and descending on the floor. It appears light.' }, { name: 'Hippos', artist: 'Taipei Zoo', description: 'The Taipei Zoo commissioned a Hippo Square featuring submerged hippos at play.', - url: 'https://i.imgur.com/6o5Vuyu.jpg', + url: 'https://react.dev/images/docs/scientists/6o5Vuyu.jpg', alt: 'A group of bronze hippo sculptures emerging from the sett sidewalk as if they were swimming.' }]; ``` @@ -1444,7 +1476,11 @@ export default function FeedbackForm() { 두 번째 `useState` 호출을 `if` 조건문 뒤로 이동해 보세요. 그러면 어떻게 오류가 발생하는지 확인할 수 있을 것입니다. +<<<<<<< HEAD 만약 [React 용으로 설정된](/learn/editor-setup#linting) 린터를 사용 중이라면 이와 같은 실수를 할 때 린트 오류가 표시될 것입니다. 로컬에서 잘못된 코드를 시도할 때 오류가 보이지 않는다면 프로젝트에 린터를 설정해야 합니다. +======= +If your linter is [configured for React](/learn/editor-setup#linting), you should see a lint error when you make a mistake like this. If you don't see an error when you try the faulty code locally, you need to set up linting for your project. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Solution> diff --git a/src/content/learn/thinking-in-react.md b/src/content/learn/thinking-in-react.md index 75d500da9..a56142354 100644 --- a/src/content/learn/thinking-in-react.md +++ b/src/content/learn/thinking-in-react.md @@ -36,9 +36,15 @@ React로 UI를 구현하기 위해서 일반적으로 다섯 가지 단계를 어떤 배경을 가지고 있냐에 따라, 디자인을 컴포넌트로 나누는 방법에 대한 관점이 달라질 수 있습니다. +<<<<<<< HEAD * **Programming**--새로운 함수나 객체를 만드는 방식으로 해봅시다. 이 중 [단일 책임 원칙](https://ko.wikipedia.org/wiki/%EB%8B%A8%EC%9D%BC_%EC%B1%85%EC%9E%84_%EC%9B%90%EC%B9%99)을 반영하고자 한다면 컴포넌트는 이상적으로는 한 번에 한 가지 일만 해야 합니다. 만약 컴포넌트가 점점 커진다면 작은 하위 컴포넌트로 쪼개져야 하겠죠. * **CSS**--클래스 선택자를 무엇으로 만들지 생각해 봅시다. (실제 컴포넌트들은 약간 더 세분되어 있습니다.) * **Design**--디자인 계층을 어떤 식으로 구성할 지 생각해 봅시다. +======= +* **Programming**--use the same techniques for deciding if you should create a new function or object. One such technique is the [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns), that is, a component should ideally only be concerned with one thing. If it ends up growing, it should be decomposed into smaller subcomponents. +* **CSS**--consider what you would make class selectors for. (However, components are a bit less granular.) +* **Design**--consider how you would organize the design's layers. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a JSON이 잘 구조화되어 있다면, 종종 이것이 UI의 컴포넌트 구조가 자연스럽게 데이터 모델에 대응된다는 것을 발견할 수 있습니다. 이는 UI와 데이터 모델은 보통 같은 정보 아키텍처, 즉 같은 구조를 가지기 때문입니다. UI를 컴포넌트로 분리하고, 각 컴포넌트가 데이터 모델에 매칭될 수 있도록 하세요. @@ -227,10 +233,17 @@ State는 앱이 기억해야 하는, 변경할 수 있는 데이터의 최소 위 데이터들을 다시 한번 순서대로 살펴봅시다. +<<<<<<< HEAD 1. 제품의 원본 목록은 **Props로 전달되었기 때문에 State가 아닙니다**. 2. 사용자가 입력한 검색어는 시간에 따라 변하고, 다른 요소로부터 계산할 수 없기 때문에 State로 볼 수 있습니다. 3. 체크박스의 값은 시간에 따라 바뀌고 다른 요소로부터 계산할 수 없기 때문에 State로 볼 수 있습니다. 4. 필터링된 제품 목록은 원본 제품 목록을 받아서 검색어와 체크박스의 값에 따라 **계산할 수 있으므로, 이는 State가 아닙니다.** +======= +1. The original list of products is **passed in as props, so it's not state.** +2. The search text seems to be state since it changes over time and can't be computed from anything. +3. The value of the checkbox seems to be state since it changes over time and can't be computed from anything. +4. The filtered list of products **isn't state because it can be computed** by taking the original list of products and filtering it according to the search text and value of the checkbox. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 따라서, 검색어와 체크박스의 값만이 State입니다! 잘하셨습니다! @@ -264,6 +277,7 @@ Props와 State는 다르지만, 함께 동작합니다. State는 보통 부모 이제 이 전략을 애플리케이션에 적용해 봅시다. +<<<<<<< HEAD 1. **State를 쓰는 컴포넌트를 찾아봅시다**: - `ProductTable`은 State에 기반한 상품 리스트를 필터링해야 합니다. (검색어와 체크 박스의 값) - `SearchBar`는 State를 표시해 주어야 합니다. (검색어와 체크 박스의 값) @@ -271,6 +285,15 @@ Props와 State는 다르지만, 함께 동작합니다. State는 보통 부모 3. **어디에 State가 존재해야 할지 정해봅시다**: 우리는`FilterableProductTable`에 검색어와 체크 박스 값을 State로 둘 겁니다. 이제 State 값은 `FilterableProductTable` 안에 있습니다. +======= +1. **Identify components that use state:** + * `ProductTable` needs to filter the product list based on that state (search text and checkbox value). + * `SearchBar` needs to display that state (search text and checkbox value). +2. **Find their common parent:** The first parent component both components share is `FilterableProductTable`. +3. **Decide where the state lives**: We'll keep the filter text and checked state values in `FilterableProductTable`. + +So the state values will live in `FilterableProductTable`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a [`useState()` Hook](/reference/react/useState)을 이용해서 State를 컴포넌트에 추가하세요. Hook은 React 기능에 "연결할 수<sup>Hook Into</sup>" 있게 해주는 특별한 함수입니다. `FilterableProductTable`의 상단에 두 개의 State 변수를 추가해서 초깃값을 명확하게 보여주세요. @@ -518,9 +541,13 @@ function FilterableProductTable({ products }) { <div> <SearchBar filterText={filterText} +<<<<<<< HEAD inStockOnly={inStockOnly} onFilterTextChange={setFilterText} onInStockOnlyChange={setInStockOnly} /> +======= + inStockOnly={inStockOnly} /> +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <ProductTable products={products} filterText={filterText} @@ -596,6 +623,108 @@ function ProductTable({ products, filterText, inStockOnly }) { ); } +<<<<<<< HEAD +======= +function SearchBar({ filterText, inStockOnly }) { + return ( + <form> + <input + type="text" + value={filterText} + placeholder="Search..."/> + <label> + <input + type="checkbox" + checked={inStockOnly} /> + {' '} + Only show products in stock + </label> + </form> + ); +} + +const PRODUCTS = [ + {category: "Fruits", price: "$1", stocked: true, name: "Apple"}, + {category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit"}, + {category: "Fruits", price: "$2", stocked: false, name: "Passionfruit"}, + {category: "Vegetables", price: "$2", stocked: true, name: "Spinach"}, + {category: "Vegetables", price: "$4", stocked: false, name: "Pumpkin"}, + {category: "Vegetables", price: "$1", stocked: true, name: "Peas"} +]; + +export default function App() { + return <FilterableProductTable products={PRODUCTS} />; +} +``` + +```css +body { + padding: 5px +} +label { + display: block; + margin-top: 5px; + margin-bottom: 5px; +} +th { + padding-top: 5px; +} +td { + padding: 2px; +} +``` + +</Sandpack> + +Notice that editing the form doesn't work yet. There is a console error in the sandbox above explaining why: + +<ConsoleBlock level="error"> + +You provided a \`value\` prop to a form field without an \`onChange\` handler. This will render a read-only field. + +</ConsoleBlock> + +In the sandbox above, `ProductTable` and `SearchBar` read the `filterText` and `inStockOnly` props to render the table, the input, and the checkbox. For example, here is how `SearchBar` populates the input value: + +```js {1,6} +function SearchBar({ filterText, inStockOnly }) { + return ( + <form> + <input + type="text" + value={filterText} + placeholder="Search..."/> +``` + +However, you haven't added any code to respond to the user actions like typing yet. This will be your final step. + + +## Step 5: Add inverse data flow {/*step-5-add-inverse-data-flow*/} + +Currently your app renders correctly with props and state flowing down the hierarchy. But to change the state according to user input, you will need to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`. + +React makes this data flow explicit, but it requires a little more typing than two-way data binding. If you try to type or check the box in the example above, you'll see that React ignores your input. This is intentional. By writing `<input value={filterText} />`, you've set the `value` prop of the `input` to always be equal to the `filterText` state passed in from `FilterableProductTable`. Since `filterText` state is never set, the input never changes. + +You want to make it so whenever the user changes the form inputs, the state updates to reflect those changes. The state is owned by `FilterableProductTable`, so only it can call `setFilterText` and `setInStockOnly`. To let `SearchBar` update the `FilterableProductTable`'s state, you need to pass these functions down to `SearchBar`: + +```js {2,3,10,11} +function FilterableProductTable({ products }) { + const [filterText, setFilterText] = useState(''); + const [inStockOnly, setInStockOnly] = useState(false); + + return ( + <div> + <SearchBar + filterText={filterText} + inStockOnly={inStockOnly} + onFilterTextChange={setFilterText} + onInStockOnlyChange={setInStockOnly} /> +``` + +Inside the `SearchBar`, you will add the `onChange` event handlers and set the parent state from them: + +```js {4,5,13,19} +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a function SearchBar({ filterText, inStockOnly, @@ -606,10 +735,131 @@ function SearchBar({ <form> <input type="text" +<<<<<<< HEAD value={filterText} placeholder="Search..." onChange={(e) => onFilterTextChange(e.target.value)} /> <label> <input +======= + value={filterText} + placeholder="Search..." + onChange={(e) => onFilterTextChange(e.target.value)} + /> + <label> + <input + type="checkbox" + checked={inStockOnly} + onChange={(e) => onInStockOnlyChange(e.target.checked)} +``` + +Now the application fully works! + +<Sandpack> + +```jsx src/App.js +import { useState } from 'react'; + +function FilterableProductTable({ products }) { + const [filterText, setFilterText] = useState(''); + const [inStockOnly, setInStockOnly] = useState(false); + + return ( + <div> + <SearchBar + filterText={filterText} + inStockOnly={inStockOnly} + onFilterTextChange={setFilterText} + onInStockOnlyChange={setInStockOnly} /> + <ProductTable + products={products} + filterText={filterText} + inStockOnly={inStockOnly} /> + </div> + ); +} + +function ProductCategoryRow({ category }) { + return ( + <tr> + <th colSpan="2"> + {category} + </th> + </tr> + ); +} + +function ProductRow({ product }) { + const name = product.stocked ? product.name : + <span style={{ color: 'red' }}> + {product.name} + </span>; + + return ( + <tr> + <td>{name}</td> + <td>{product.price}</td> + </tr> + ); +} + +function ProductTable({ products, filterText, inStockOnly }) { + const rows = []; + let lastCategory = null; + + products.forEach((product) => { + if ( + product.name.toLowerCase().indexOf( + filterText.toLowerCase() + ) === -1 + ) { + return; + } + if (inStockOnly && !product.stocked) { + return; + } + if (product.category !== lastCategory) { + rows.push( + <ProductCategoryRow + category={product.category} + key={product.category} /> + ); + } + rows.push( + <ProductRow + product={product} + key={product.name} /> + ); + lastCategory = product.category; + }); + + return ( + <table> + <thead> + <tr> + <th>Name</th> + <th>Price</th> + </tr> + </thead> + <tbody>{rows}</tbody> + </table> + ); +} + +function SearchBar({ + filterText, + inStockOnly, + onFilterTextChange, + onInStockOnlyChange +}) { + return ( + <form> + <input + type="text" + value={filterText} placeholder="Search..." + onChange={(e) => onFilterTextChange(e.target.value)} /> + <label> + <input +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a type="checkbox" checked={inStockOnly} onChange={(e) => onInStockOnlyChange(e.target.checked)} /> diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md index 23ed57e67..32137de65 100644 --- a/src/content/learn/tutorial-tic-tac-toe.md +++ b/src/content/learn/tutorial-tic-tac-toe.md @@ -341,7 +341,11 @@ import './styles.css'; import App from './App'; ``` +<<<<<<< HEAD 1~5줄은 아래에 있는 필요한 모든 코드를 한 곳으로 가져옵니다. +======= +Lines 1-5 bring all the necessary pieces together: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a * React * 웹 브라우저와 상호작용하는 React의 라이브러리 (React DOM) @@ -555,7 +559,11 @@ export default function Board() { } ``` +<<<<<<< HEAD 브라우저의 `div`와 달리, 직접 만든 `Board`와 `Square` 컴포넌트는 반드시 대문자로 시작해야 한다는 점에 유의하세요. +======= +Note how unlike the browser `div`s, your own components `Board` and `Square` must start with a capital letter. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 보드를 살펴보겠습니다. @@ -1098,7 +1106,11 @@ function Square({ value, onSquareClick }) { } ``` +<<<<<<< HEAD 이제 `onSquareClick` Prop을 `Board` 컴포넌트의 `handleClick` 함수와 연결하세요. `onSquareClick` 함수를 `handleClick`과 연결하려면 첫 번째 `Square` 컴포넌트의 `onSquareClick` Prop에 해당 함수를 전달하면 됩니다. +======= +Now you'll connect the `onSquareClick` prop to a function in the `Board` component that you'll name `handleClick`. To connect `onSquareClick` to `handleClick` you'll pass a function to the `onSquareClick` prop of the first `Square` component: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js {7} export default function Board() { @@ -2077,13 +2089,21 @@ export default function Game() { } ``` +<<<<<<< HEAD 아래에서 코드가 어떻게 보이는지 확인할 수 있습니다. 개발자 도구 콘솔에 다음과 같은 오류 메시지가 표시되어야 합니다: +======= +You can see what your code should look like below. Note that you should see an error in the developer tools console that says: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <ConsoleBlock level="warning"> 경고: 배열 또는 반복자의 각 자식 요소는 고유한 "key" 속성을 가져야 합니다. `Game`의 렌더 메서드를 확인하세요. </ConsoleBlock> +<<<<<<< HEAD 다음 부문에서 이 오류를 수정하겠습니다. +======= +You'll fix this error in the next section. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Sandpack> diff --git a/src/content/learn/updating-objects-in-state.md b/src/content/learn/updating-objects-in-state.md index d12b263a8..5246fa69e 100644 --- a/src/content/learn/updating-objects-in-state.md +++ b/src/content/learn/updating-objects-in-state.md @@ -296,7 +296,11 @@ setPerson({ }); ``` +<<<<<<< HEAD 이제 폼이 동작합니다! +======= +Now the form works! +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 각 input 필드에 대해 분리된 state를 선언하지 않았음을 기억하세요. 큰 폼들은 올바르게 업데이트한다면, 한 객체에 모든 데이터를 그룹화하여 저장하는 것이 편리합니다. @@ -373,7 +377,11 @@ input { margin-left: 5px; margin-bottom: 5px; } </Sandpack> +<<<<<<< HEAD `...` 전개 문법은 "얕다"는 점을 알아두세요. 이것은 한 레벨 깊이의 내용만 복사합니다. 빠르지만, 중첩된 프로퍼티를 업데이트하고 싶다면 한 번 이상 사용해야 한다는 뜻이기도 합니다. +======= +Note that the `...` spread syntax is "shallow"--it only copies things one level deep. This makes it fast, but it also means that if you want to update a nested property, you'll have to use it more than once. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <DeepDive> @@ -457,7 +465,7 @@ const [person, setPerson] = useState({ artwork: { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', } }); ``` @@ -501,7 +509,7 @@ export default function Form() { artwork: { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', } }); @@ -608,7 +616,7 @@ let obj = { artwork: { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', } }; ``` @@ -619,7 +627,7 @@ let obj = { let obj1 = { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', }; let obj2 = { @@ -634,7 +642,7 @@ let obj2 = { let obj1 = { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', }; let obj2 = { @@ -691,7 +699,7 @@ export default function Form() { artwork: { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', } }); diff --git a/src/content/learn/writing-markup-with-jsx.md b/src/content/learn/writing-markup-with-jsx.md index d5f9c337e..84224d30e 100644 --- a/src/content/learn/writing-markup-with-jsx.md +++ b/src/content/learn/writing-markup-with-jsx.md @@ -71,7 +71,11 @@ JSX와 React는 서로 다른 별개의 개념입니다. 종종 함께 사용되 ```html <h1>Hedy Lamarr's Todos</h1> <img +<<<<<<< HEAD src="https://i.imgur.com/yXOvdOSs.jpg" +======= + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Hedy Lamarr" class="photo" > @@ -103,7 +107,11 @@ export default function TodoList() { // 이것은 동작하지 않습니다! <h1>Hedy Lamarr's Todos</h1> <img +<<<<<<< HEAD src="https://i.imgur.com/yXOvdOSs.jpg" +======= + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Hedy Lamarr" class="photo" > @@ -142,7 +150,11 @@ img { height: 90px } <div> <h1>Hedy Lamarr's Todos</h1> <img +<<<<<<< HEAD src="https://i.imgur.com/yXOvdOSs.jpg" +======= + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Hedy Lamarr" class="photo" > @@ -159,7 +171,11 @@ img { height: 90px } <> <h1>Hedy Lamarr's Todos</h1> <img +<<<<<<< HEAD src="https://i.imgur.com/yXOvdOSs.jpg" +======= + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Hedy Lamarr" class="photo" > @@ -188,7 +204,11 @@ JSX에서는 태그를 명시적으로 닫아야 합니다. `<img>`처럼 자체 ```js {2-6,8-10} <> <img +<<<<<<< HEAD src="https://i.imgur.com/yXOvdOSs.jpg" +======= + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Hedy Lamarr" class="photo" /> @@ -208,7 +228,11 @@ JSX는 JavaScript로 바뀌고 JSX에서 작성된 어트리뷰트는 JavaScript ```js {4} <img +<<<<<<< HEAD src="https://i.imgur.com/yXOvdOSs.jpg" +======= + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Hedy Lamarr" className="photo" /> @@ -236,7 +260,11 @@ export default function TodoList() { <> <h1>Hedy Lamarr's Todos</h1> <img +<<<<<<< HEAD src="https://i.imgur.com/yXOvdOSs.jpg" +======= + src="https://react.dev/images/docs/scientists/yXOvdOSs.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Hedy Lamarr" className="photo" /> diff --git a/src/content/learn/your-first-component.md b/src/content/learn/your-first-component.md index a4aa90b63..a72a0de63 100644 --- a/src/content/learn/your-first-component.md +++ b/src/content/learn/your-first-component.md @@ -63,7 +63,7 @@ HTML 태그와 마찬가지로 컴포넌트를 작성, 순서 지정 및 중첩 export default function Profile() { return ( <img - src="https://i.imgur.com/MK3eW3Am.jpg" + src="https://react.dev/images/docs/scientists/MK3eW3Am.jpg" alt="Katherine Johnson" /> ) @@ -99,7 +99,7 @@ React 컴포넌트는 일반 JavaScript 함수이지만, **이름은 대문자 반환문은 이 컴포넌트에서처럼 한 줄에 모두 작성할 수 있습니다. ```js -return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />; +return <img src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" />; ``` 그러나 마크업이 모두 `return` 키워드와 같은 라인에 있지 않은 경우에는 다음과 같이 괄호로 묶어야 합니다. @@ -107,7 +107,7 @@ return <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" />; ```js return ( <div> - <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" /> + <img src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> </div> ); ``` @@ -128,7 +128,7 @@ return ( function Profile() { return ( <img - src="https://i.imgur.com/MK3eW3As.jpg" + src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> ); @@ -164,9 +164,9 @@ img { margin: 0 10px 10px 0; height: 90px; } ```html <section> <h1>Amazing scientists</h1> - <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" /> - <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" /> - <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" /> + <img src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> + <img src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> + <img src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> </section> ``` @@ -248,7 +248,7 @@ root 컴포넌트를 내보내지 않았기 때문에 이 샌드박스는 작동 function Profile() { return ( <img - src="https://i.imgur.com/lICfvbD.jpg" + src="https://react.dev/images/docs/scientists/lICfvbD.jpg" alt="Aklilu Lemma" /> ); @@ -273,7 +273,7 @@ img { height: 181px; } export default function Profile() { return ( <img - src="https://i.imgur.com/lICfvbD.jpg" + src="https://react.dev/images/docs/scientists/lICfvbD.jpg" alt="Aklilu Lemma" /> ); @@ -306,7 +306,7 @@ img { height: 181px; } ```js export default function Profile() { return - <img src="https://i.imgur.com/jA8hHMpm.jpg" alt="Katsuko Saruhashi" />; + <img src="https://react.dev/images/docs/scientists/jA8hHMpm.jpg" alt="Katsuko Saruhashi" />; } ``` @@ -324,7 +324,7 @@ img { height: 180px; } ```js export default function Profile() { - return <img src="https://i.imgur.com/jA8hHMpm.jpg" alt="Katsuko Saruhashi" />; + return <img src="https://react.dev/images/docs/scientists/jA8hHMpm.jpg" alt="Katsuko Saruhashi" />; } ``` @@ -342,7 +342,11 @@ img { height: 180px; } export default function Profile() { return ( <img +<<<<<<< HEAD src="https://i.imgur.com/jA8hHMpm.jpg" +======= + src="https://react.dev/images/docs/scientists/jA8hHMpm.jpg" +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a alt="Katsuko Saruhashi" /> ); @@ -367,7 +371,7 @@ img { height: 180px; } function profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); @@ -403,7 +407,7 @@ React 컴포넌트 이름은 대문자로 시작해야 합니다. function Profile() { return ( <img - src="https://i.imgur.com/QIrZWGIs.jpg" + src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg" alt="Alan L. Hart" /> ); diff --git a/src/content/reference/dev-tools/react-performance-tracks.md b/src/content/reference/dev-tools/react-performance-tracks.md index 03e16f236..9d4b2d711 100644 --- a/src/content/reference/dev-tools/react-performance-tracks.md +++ b/src/content/reference/dev-tools/react-performance-tracks.md @@ -138,7 +138,11 @@ Scheduler는 우선순위가 다른 작업을 관리하는 데 사용되는 Reac #### 서버 요청 {/*server-requests*/} +<<<<<<< HEAD 서버 요청 트랙은 최종적으로 React 서버 컴포넌트로 귀결되는 모든 Promise를 시각화합니다. 여기에는 `fetch` 호출이나 비동기 Node.js 파일 작업과 같은 모든 비동기(async) 작업이 포함됩니다. +======= +The Server Requests track visualized all Promises that eventually end up in a React Server Component. This includes any `async` operations like calling `fetch` or async Node.js file operations. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a React는 서드 파티 코드 내부에서 시작된 Promise를 **퍼스트 파티(1st party) 코드**를 차단하는 전체 작업의 지속 시간을 나타내는 단일 스팬으로 결합하려고 시도합니다. 예를 들어, 내부적으로 `fetch`를 여러 번 호출하는 서드 파티 라이브러리 메서드 `getUser`는 여러 `fetch` 스팬을 표시하는 대신 `getUser`라는 단일 스팬으로 표현됩니다. diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index 1fb463b3a..ce6a979f6 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -90,6 +90,11 @@ React는 `root`에 `<App />`을 표시하고 그 안에 있는 DOM을 관리합 * 렌더링이 시작된 이후에는 동기적으로 실행되지만, `root.render(...)` 자체는 비동기적입니다. 즉, `root.render()` 이후에 작성된 코드가 해당 렌더링의 `useLayoutEffect`나 `useEffect`보다 먼저 실행될 수 있습니다. 일반적인 상황에서는 이러한 동작도 문제 없이 잘 작동하며, 대부분 수정이 필요하지 않습니다. 다만, Effect의 실행 순서가 중요한 경우에는 [`flushSync`](/reference/react-dom/flushSync)로 `root.render(...)` 호출을 감싸면 초기 렌더링이 완전히 동기적으로 실행되도록 보장할 수 있습니다. +<<<<<<< HEAD +======= +* Although rendering is synchronous once it starts, `root.render(...)` is not. This means code after `root.render()` may run before any effects (`useLayoutEffect`, `useEffect`) of that specific render are fired. This is usually fine and rarely needs adjustment. In rare cases where effect timing matters, you can wrap `root.render(...)` in [`flushSync`](https://react.dev/reference/react-dom/flushSync) to ensure the initial render runs fully synchronously. + +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js const root = createRoot(document.getElementById('root')); root.render(<App />); @@ -111,7 +116,11 @@ root.unmount(); 이 함수는 주로 React 루트의 DOM 노드(또는 그 조상 노드)가 다른 코드에 의해 DOM에서 제거될 수 있는 경우에 유용합니다. 예를 들어 DOM에서 비활성 탭을 제거하는 jQuery 탭 패널을 상상해 보세요. 탭이 제거되면 그 안에 있는 모든 것(내부의 React 루트를 포함)이 DOM에서 제거됩니다. 이 경우 `root.unmount`를 호출하여 제거된 루트의 콘텐츠 관리를 "중지"하도록 React에 지시해야 합니다. 그렇지 않으면 제거된 루트 내부의 컴포넌트는 구독과 같은 전역 리소스를 정리하고 확보하는 법을 모르는 채로 있게 됩니다. +<<<<<<< HEAD `root.unmount`를 호출하면 루트에 있는 모든 컴포넌트가 마운트 해제되고, 트리상의 이벤트 핸들러나 State가 제거되며, 루트 DOM 노드에서 React가 "분리"됩니다. +======= +Calling `root.unmount` will unmount all the components in the root and "detach" React from the root DOM node, including removing any event handlers or state in the tree. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 매개변수 {/*root-unmount-parameters*/} @@ -195,7 +204,11 @@ function Counter() { </Sandpack> +<<<<<<< HEAD **앱이 온전히 React만으로 작성된 경우, 추가적으로 루트를 더 만들거나 [`root.render`](#root-render)를 다시 호출할 필요가 없습니다.** +======= +**If your app is fully built with React, you shouldn't need to create any more roots, or to call [`root.render`](#root-render) again.** +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 이 시점부터 React는 전체 앱의 DOM을 관리합니다. 컴포넌트를 더 추가하려면 [ `App` 컴포넌트 안에 중첩](/learn/importing-and-exporting-components)시키세요. UI 업데이트는 각 컴포넌트의 [State를 통해](/reference/react/useState) 수행할 수 있습니다. 모달이나 툴팁과 같은 추가 콘텐츠를 DOM 노드 외부에 표시해야 하는 경우 [Portal로 렌더링](/reference/react-dom/createPortal)하세요. @@ -506,7 +519,11 @@ Warning: You passed a second argument to root.render(...) but it only accepts on // 🚩 잘못된 방법: root.render는 하나의 인자만 받습니다. root.render(App, {onUncaughtError}); +<<<<<<< HEAD // ✅ 올바른 방법: 옵션은 createRoot에 전달합니다. +======= +// ✅ Correct: pass options to createRoot. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a const root = createRoot(container, {onUncaughtError}); root.render(<App />); ``` diff --git a/src/content/reference/react-dom/components/common.md b/src/content/reference/react-dom/components/common.md index e7cffb85b..1fc5afa77 100644 --- a/src/content/reference/react-dom/components/common.md +++ b/src/content/reference/react-dom/components/common.md @@ -40,6 +40,7 @@ title: "공통 컴포넌트 (예: <div>)" 아래의 표준 DOM Props는 내장된 모든 컴포넌트에서 지원합니다. +<<<<<<< HEAD * [`accessKey`](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/accesskey): 문자열 타입입니다. 요소의 바로 가기 키를 지정합니다. [일반적으로 권장하지 않습니다.](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/accesskey) * [`aria-*`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes): ARIA 속성을 사용하면 이 요소에 대한 접근성 트리 정보를 지정할 수 있습니다. 전체적인 레퍼런스는 [ARIA 어트리뷰트](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes)를 참조하세요. React에서 모든 ARIA 어트리뷰트의 이름은 HTML에서의 이름과 완전히 동일합니다. * [`autoCapitalize`](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/autocapitalize): 문자열 타입입니다. 사용자의 입력을 대문자로 표시할지 여부와 방법을 지정합니다. @@ -154,6 +155,122 @@ title: "공통 컴포넌트 (예: <div>)" * [`tabIndex`](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/tabindex): 숫자 타입입니다. 기본 탭 버튼 동작을 재정의합니다. [`-1`과 `0` 이외의 값은 사용하지 마십시오.](https://www.tpgi.com/using-the-tabindex-attribute/) * [`title`](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/title): 문자열 타입입니다. 요소의 툴팁 텍스트를 지정합니다. * [`translate`](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/translate): `'yes'`나`'no'` 중 하나입니다. `'no'` 를 전달하면 요소의 콘텐츠가 번역에서 제외됩니다. +======= +* [`accessKey`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey): A string. Specifies a keyboard shortcut for the element. [Not generally recommended.](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey#accessibility_concerns) +* [`aria-*`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes): ARIA attributes let you specify the accessibility tree information for this element. See [ARIA attributes](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes) for a complete reference. In React, all ARIA attribute names are exactly the same as in HTML. +* [`autoCapitalize`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize): A string. Specifies whether and how the user input should be capitalized. +* [`className`](https://developer.mozilla.org/en-US/docs/Web/API/Element/className): A string. Specifies the element's CSS class name. [Read more about applying CSS styles.](#applying-css-styles) +* [`contentEditable`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable): A boolean. If `true`, the browser lets the user edit the rendered element directly. This is used to implement rich text input libraries like [Lexical.](https://lexical.dev/) React warns if you try to pass React children to an element with `contentEditable={true}` because React will not be able to update its content after user edits. +* [`data-*`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*): Data attributes let you attach some string data to the element, for example `data-fruit="banana"`. In React, they are not commonly used because you would usually read data from props or state instead. +* [`dir`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir): Either `'ltr'` or `'rtl'`. Specifies the text direction of the element. +* [`draggable`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable): A boolean. Specifies whether the element is draggable. Part of [HTML Drag and Drop API.](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API) +* [`enterKeyHint`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/enterKeyHint): A string. Specifies which action to present for the enter key on virtual keyboards. +* [`htmlFor`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/htmlFor): A string. For [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) and [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output), lets you [associate the label with some control.](/reference/react-dom/components/input#providing-a-label-for-an-input) Same as [`for` HTML attribute.](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/for) React uses the standard DOM property names (`htmlFor`) instead of HTML attribute names. +* [`hidden`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden): A boolean or a string. Specifies whether the element should be hidden. +* [`id`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id): A string. Specifies a unique identifier for this element, which can be used to find it later or connect it with other elements. Generate it with [`useId`](/reference/react/useId) to avoid clashes between multiple instances of the same component. +* [`is`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is): A string. If specified, the component will behave like a [custom element.](/reference/react-dom/components#custom-html-elements) +* [`inputMode`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode): A string. Specifies what kind of keyboard to display (for example, text, number or telephone). +* [`itemProp`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/itemprop): A string. Specifies which property the element represents for structured data crawlers. +* [`lang`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang): A string. Specifies the language of the element. +* [`onAnimationEnd`](https://developer.mozilla.org/en-US/docs/Web/API/Element/animationend_event): An [`AnimationEvent` handler](#animationevent-handler) function. Fires when a CSS animation completes. +* `onAnimationEndCapture`: A version of `onAnimationEnd` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onAnimationIteration`](https://developer.mozilla.org/en-US/docs/Web/API/Element/animationiteration_event): An [`AnimationEvent` handler](#animationevent-handler) function. Fires when an iteration of a CSS animation ends, and another one begins. +* `onAnimationIterationCapture`: A version of `onAnimationIteration` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onAnimationStart`](https://developer.mozilla.org/en-US/docs/Web/API/Element/animationstart_event): An [`AnimationEvent` handler](#animationevent-handler) function. Fires when a CSS animation starts. +* `onAnimationStartCapture`: `onAnimationStart`, but fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onAuxClick`](https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when a non-primary pointer button was clicked. +* `onAuxClickCapture`: A version of `onAuxClick` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* `onBeforeInput`: An [`InputEvent` handler](#inputevent-handler) function. Fires before the value of an editable element is modified. React does *not* yet use the native [`beforeinput`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/beforeinput_event) event, and instead attempts to polyfill it using other events. +* `onBeforeInputCapture`: A version of `onBeforeInput` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* `onBlur`: A [`FocusEvent` handler](#focusevent-handler) function. Fires when an element lost focus. Unlike the built-in browser [`blur`](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event) event, in React the `onBlur` event bubbles. +* `onBlurCapture`: A version of `onBlur` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onClick`](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the primary button was clicked on the pointing device. +* `onClickCapture`: A version of `onClick` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onCompositionStart`](https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionstart_event): A [`CompositionEvent` handler](#compositionevent-handler) function. Fires when an [input method editor](https://developer.mozilla.org/en-US/docs/Glossary/Input_method_editor) starts a new composition session. +* `onCompositionStartCapture`: A version of `onCompositionStart` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onCompositionEnd`](https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionend_event): A [`CompositionEvent` handler](#compositionevent-handler) function. Fires when an [input method editor](https://developer.mozilla.org/en-US/docs/Glossary/Input_method_editor) completes or cancels a composition session. +* `onCompositionEndCapture`: A version of `onCompositionEnd` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onCompositionUpdate`](https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionupdate_event): A [`CompositionEvent` handler](#compositionevent-handler) function. Fires when an [input method editor](https://developer.mozilla.org/en-US/docs/Glossary/Input_method_editor) receives a new character. +* `onCompositionUpdateCapture`: A version of `onCompositionUpdate` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onContextMenu`](https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the user tries to open a context menu. +* `onContextMenuCapture`: A version of `onContextMenu` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onCopy`](https://developer.mozilla.org/en-US/docs/Web/API/Element/copy_event): A [`ClipboardEvent` handler](#clipboardevent-handler) function. Fires when the user tries to copy something into the clipboard. +* `onCopyCapture`: A version of `onCopy` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onCut`](https://developer.mozilla.org/en-US/docs/Web/API/Element/cut_event): A [`ClipboardEvent` handler](#clipboardevent-handler) function. Fires when the user tries to cut something into the clipboard. +* `onCutCapture`: A version of `onCut` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* `onDoubleClick`: A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the user clicks twice. Corresponds to the browser [`dblclick` event.](https://developer.mozilla.org/en-US/docs/Web/API/Element/dblclick_event) +* `onDoubleClickCapture`: A version of `onDoubleClick` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onDrag`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drag_event): A [`DragEvent` handler](#dragevent-handler) function. Fires while the user is dragging something. +* `onDragCapture`: A version of `onDrag` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onDragEnd`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragend_event): A [`DragEvent` handler](#dragevent-handler) function. Fires when the user stops dragging something. +* `onDragEndCapture`: A version of `onDragEnd` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onDragEnter`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragenter_event): A [`DragEvent` handler](#dragevent-handler) function. Fires when the dragged content enters a valid drop target. +* `onDragEnterCapture`: A version of `onDragEnter` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onDragOver`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragover_event): A [`DragEvent` handler](#dragevent-handler) function. Fires on a valid drop target while the dragged content is dragged over it. You must call `e.preventDefault()` here to allow dropping. +* `onDragOverCapture`: A version of `onDragOver` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onDragStart`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragstart_event): A [`DragEvent` handler](#dragevent-handler) function. Fires when the user starts dragging an element. +* `onDragStartCapture`: A version of `onDragStart` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onDrop`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event): A [`DragEvent` handler](#dragevent-handler) function. Fires when something is dropped on a valid drop target. +* `onDropCapture`: A version of `onDrop` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* `onFocus`: A [`FocusEvent` handler](#focusevent-handler) function. Fires when an element receives focus. Unlike the built-in browser [`focus`](https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event) event, in React the `onFocus` event bubbles. +* `onFocusCapture`: A version of `onFocus` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onGotPointerCapture`](https://developer.mozilla.org/en-US/docs/Web/API/Element/gotpointercapture_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when an element programmatically captures a pointer. +* `onGotPointerCaptureCapture`: A version of `onGotPointerCapture` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onKeyDown`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event): A [`KeyboardEvent` handler](#keyboardevent-handler) function. Fires when a key is pressed. +* `onKeyDownCapture`: A version of `onKeyDown` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onKeyPress`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event): A [`KeyboardEvent` handler](#keyboardevent-handler) function. Deprecated. Use `onKeyDown` or `onBeforeInput` instead. +* `onKeyPressCapture`: A version of `onKeyPress` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onKeyUp`](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event): A [`KeyboardEvent` handler](#keyboardevent-handler) function. Fires when a key is released. +* `onKeyUpCapture`: A version of `onKeyUp` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onLostPointerCapture`](https://developer.mozilla.org/en-US/docs/Web/API/Element/lostpointercapture_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when an element stops capturing a pointer. +* `onLostPointerCaptureCapture`: A version of `onLostPointerCapture` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onMouseDown`](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousedown_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the pointer is pressed down. +* `onMouseDownCapture`: A version of `onMouseDown` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onMouseEnter`](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseenter_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the pointer moves inside an element. Does not have a capture phase. Instead, `onMouseLeave` and `onMouseEnter` propagate from the element being left to the one being entered. +* [`onMouseLeave`](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseleave_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the pointer moves outside an element. Does not have a capture phase. Instead, `onMouseLeave` and `onMouseEnter` propagate from the element being left to the one being entered. +* [`onMouseMove`](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the pointer changes coordinates. +* `onMouseMoveCapture`: A version of `onMouseMove` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onMouseOut`](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseout_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the pointer moves outside an element, or if it moves into a child element. +* `onMouseOutCapture`: A version of `onMouseOut` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onMouseUp`](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseup_event): A [`MouseEvent` handler](#mouseevent-handler) function. Fires when the pointer is released. +* `onMouseUpCapture`: A version of `onMouseUp` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onPointerCancel`](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointercancel_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when the browser cancels a pointer interaction. +* `onPointerCancelCapture`: A version of `onPointerCancel` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onPointerDown`](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointerdown_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when a pointer becomes active. +* `onPointerDownCapture`: A version of `onPointerDown` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onPointerEnter`](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointerenter_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when a pointer moves inside an element. Does not have a capture phase. Instead, `onPointerLeave` and `onPointerEnter` propagate from the element being left to the one being entered. +* [`onPointerLeave`](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointerleave_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when a pointer moves outside an element. Does not have a capture phase. Instead, `onPointerLeave` and `onPointerEnter` propagate from the element being left to the one being entered. +* [`onPointerMove`](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointermove_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when a pointer changes coordinates. +* `onPointerMoveCapture`: A version of `onPointerMove` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onPointerOut`](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointerout_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when a pointer moves outside an element, if the pointer interaction is cancelled, and [a few other reasons.](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointerout_event) +* `onPointerOutCapture`: A version of `onPointerOut` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onPointerUp`](https://developer.mozilla.org/en-US/docs/Web/API/Element/pointerup_event): A [`PointerEvent` handler](#pointerevent-handler) function. Fires when a pointer is no longer active. +* `onPointerUpCapture`: A version of `onPointerUp` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onPaste`](https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event): A [`ClipboardEvent` handler](#clipboardevent-handler) function. Fires when the user tries to paste something from the clipboard. +* `onPasteCapture`: A version of `onPaste` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onScroll`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scroll_event): An [`Event` handler](#event-handler) function. Fires when an element has been scrolled. This event does not bubble. +* `onScrollCapture`: A version of `onScroll` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onSelect`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select_event): An [`Event` handler](#event-handler) function. Fires after the selection inside an editable element like an input changes. React extends the `onSelect` event to work for `contentEditable={true}` elements as well. In addition, React extends it to fire for empty selection and on edits (which may affect the selection). +* `onSelectCapture`: A version of `onSelect` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onTouchCancel`](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchcancel_event): A [`TouchEvent` handler](#touchevent-handler) function. Fires when the browser cancels a touch interaction. +* `onTouchCancelCapture`: A version of `onTouchCancel` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onTouchEnd`](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchend_event): A [`TouchEvent` handler](#touchevent-handler) function. Fires when one or more touch points are removed. +* `onTouchEndCapture`: A version of `onTouchEnd` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onTouchMove`](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchmove_event): A [`TouchEvent` handler](#touchevent-handler) function. Fires one or more touch points are moved. +* `onTouchMoveCapture`: A version of `onTouchMove` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onTouchStart`](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchstart_event): A [`TouchEvent` handler](#touchevent-handler) function. Fires when one or more touch points are placed. +* `onTouchStartCapture`: A version of `onTouchStart` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onTransitionEnd`](https://developer.mozilla.org/en-US/docs/Web/API/Element/transitionend_event): A [`TransitionEvent` handler](#transitionevent-handler) function. Fires when a CSS transition completes. +* `onTransitionEndCapture`: A version of `onTransitionEnd` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`onWheel`](https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event): A [`WheelEvent` handler](#wheelevent-handler) function. Fires when the user rotates a wheel button. +* `onWheelCapture`: A version of `onWheel` that fires in the [capture phase.](/learn/responding-to-events#capture-phase-events) +* [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles): A string. Specifies the element role explicitly for assistive technologies. +* [`slot`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles): A string. Specifies the slot name when using shadow DOM. In React, an equivalent pattern is typically achieved by passing JSX as props, for example `<Layout left={<Sidebar />} right={<Content />} />`. +* [`spellCheck`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck): A boolean or null. If explicitly set to `true` or `false`, enables or disables spellchecking. +* [`tabIndex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex): A number. Overrides the default Tab button behavior. [Avoid using values other than `-1` and `0`.](https://www.tpgi.com/using-the-tabindex-attribute/) +* [`title`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title): A string. Specifies the tooltip text for the element. +* [`translate`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/translate): Either `'yes'` or `'no'`. Passing `'no'` excludes the element content from being translated. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 사용자 정의 어트리뷰트를 Props로 전달할 수도 있습니다. (예: `mycustomprop="someValue"`) 이는 서드파티 라이브러리와 통합할 때 유용할 수 있습니다. 사용자 정의 어트리뷰트의 이름은 소문자여야 하며 `on`으로 시작하지 않아야 합니다. 값은 문자열로 변환됩니다. `null` 또는 `undefined`를 전달하면 사용자 정의 어트리뷰트가 제거됩니다. @@ -301,7 +418,18 @@ React는 *다른* `ref` 콜백을 전달할 때마다 `ref` 콜백도 호출합 #### 프로퍼티 {/*react-event-object-properties*/} +<<<<<<< HEAD React 이벤트 객체는 표준 [`Event`](https://developer.mozilla.org/ko/docs/Web/API/Event) 프로퍼티의 일부를 구현했습니다. +======= +* [`bubbles`](https://developer.mozilla.org/en-US/docs/Web/API/Event/bubbles): A boolean. Returns whether the event bubbles through the DOM. +* [`cancelable`](https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable): A boolean. Returns whether the event can be canceled. +* [`currentTarget`](https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget): A DOM node. Returns the node to which the current handler is attached in the React tree. +* [`defaultPrevented`](https://developer.mozilla.org/en-US/docs/Web/API/Event/defaultPrevented): A boolean. Returns whether `preventDefault` was called. +* [`eventPhase`](https://developer.mozilla.org/en-US/docs/Web/API/Event/eventPhase): A number. Returns which phase the event is currently in. +* [`isTrusted`](https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted): A boolean. Returns whether the event was initiated by user. +* [`target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target): A DOM node. Returns the node on which the event has occurred (which could be a distant child). +* [`timeStamp`](https://developer.mozilla.org/en-US/docs/Web/API/Event/timeStamp): A number. Returns the time when the event occurred. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a * [`bubbles`](https://developer.mozilla.org/ko/docs/Web/API/Event/bubbles): 불리언 타입입니다. 이벤트가 DOM을 통해 버블링되는지 여부를 반환합니다. * [`cancelable`](https://developer.mozilla.org/ko/docs/Web/API/Event/cancelable): 불리언 타입입니다. 이벤트를 취소할 수 있는지를 반환합니다. @@ -664,7 +792,11 @@ React 이벤트 객체는 표준 [`Event`](https://developer.mozilla.org/ko/docs * [`touches`](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/touches) * [`targetTouches`](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/targetTouches) +<<<<<<< HEAD 또한 상속된 [`UIEvent`](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent)의 프로퍼티도 포함합니다. +======= + It also includes the inherited [`UIEvent`](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent) properties: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a * [`detail`](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail) * [`view`](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/view) @@ -796,7 +928,7 @@ import Avatar from './Avatar.js'; const user = { name: 'Hedy Lamarr', - imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg', + imageUrl: 'https://react.dev/images/docs/scientists/yXOvdOSs.jpg', imageSize: 90, }; diff --git a/src/content/reference/react-dom/components/index.md b/src/content/reference/react-dom/components/index.md index 9f27a43af..6fb98284c 100644 --- a/src/content/reference/react-dom/components/index.md +++ b/src/content/reference/react-dom/components/index.md @@ -205,7 +205,7 @@ root.render(<App />); export class MyElement extends HTMLElement { constructor() { super(); - // The value here will be overwritten by React + // The value here will be overwritten by React // when initialized as an element this.value = undefined; } diff --git a/src/content/reference/react-dom/components/link.md b/src/content/reference/react-dom/components/link.md index 5e266fcec..c605baf9f 100644 --- a/src/content/reference/react-dom/components/link.md +++ b/src/content/reference/react-dom/components/link.md @@ -151,7 +151,11 @@ export default function SiteMapPage() { ### 스타일시트 우선순위 제어하기 {/*controlling-stylesheet-precedence*/} +<<<<<<< HEAD 스타일시트는 서로 충돌할 수 있으며, 이 경우 브라우저는 문서에서 나중에 오는 스타일시트를 적용합니다. React는 `precedence` 속성을 사용하여 스타일시트의 순서를 제어할 수 있도록 합니다. 이 예시에서는 세 개의 컴포넌트가 스타일시트를 렌더링하며, 동일한 `precedence` 값을 가진 스타일시트는 `<head>`에서 함께 그룹화됩니다. +======= +Stylesheets can conflict with each other, and when they do, the browser goes with the one that comes later in the document. React lets you control the order of stylesheets with the `precedence` prop. In this example, three components render stylesheets, and the ones with the same precedence are grouped together in the `<head>`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <SandpackWithHTMLOutput> diff --git a/src/content/reference/react-dom/components/meta.md b/src/content/reference/react-dom/components/meta.md index c3a0dc1ba..1874af607 100644 --- a/src/content/reference/react-dom/components/meta.md +++ b/src/content/reference/react-dom/components/meta.md @@ -34,7 +34,15 @@ meta: "<meta>" 다음 속성 중 _하나만_ 가져야 합니다. `name`, `httpEquiv`, `charset`, `itemProp`. +<<<<<<< HEAD `<meta>` 컴포넌트는 지정된 Props에 따라 각각 다른 동작을 합니다. +======= +* `name`: a string. Specifies the [kind of metadata](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name) to be attached to the document. +* `charset`: a string. Specifies the character set used by the document. The only valid value is `"utf-8"`. +* `httpEquiv`: a string. Specifies a directive for processing the document. +* `itemProp`: a string. Specifies metadata about a particular item within the document rather than the document as a whole. +* `content`: a string. Specifies the metadata to be attached when used with the `name` or `itemProp` props or the behavior of the directive when used with the `httpEquiv` prop. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a * `name`: 문자열. 문서에 첨부될 [메타데이터 종류](https://developer.mozilla.org/ko/docs/Web/HTML/Element/meta/name)를 지정합니다. * `charset`: 문자열. 문서에서 사용되는 문자 인코딩을 지원합니다. 유효한 값은 `"utf-8"` 뿐 입니다. @@ -42,11 +50,17 @@ meta: "<meta>" * `itemProp`: 문자열. 문서 전체가 아닌 문서 내 특정 항목에 대한 메타데이터를 지정합니다. * `content`: 문자열. `name` 또는 `itemProp` Props와 함께 사용 시 첨부될 메타데이터를 지정하거나, `httpEquiv` Props와 함께 사용 시 지시 사항의 동작을 지정합니다. +<<<<<<< HEAD #### 특수 렌더링 동작 {/*special-rendering-behavior*/} React는 `<meta>` 컴포넌트가 React 트리 어디에서 렌더링되든 상관없이 해당하는 DOM 요소를 항상 문서의 `<head>` 내에 배치합니다. DOM 내에서 `<head>`는 `<meta>`가 존재할 수 있는 유일한 유효한 위치이지만, 특정 페이지를 나타내는 컴포넌트가 `<meta>` 컴포넌트를 자체적으로 렌더링할 수 있다는 점이 편리하고, 구성 가능성을 유지해 줍니다. 단, `<meta>`에 [`itemProp`](https://developer.mozilla.org/ko/docs/Web/HTML/Global_attributes/itemprop) Props가 있는 경우에는 예외입니다. 이 경우에는 문서에 대한 메타데이터가 아닌 페이지의 특정 부분에 대한 메타데이터를 나타내므로 특수한 동작이 적용되지 않습니다. +======= +React will always place the DOM element corresponding to the `<meta>` component within the document’s `<head>`, regardless of where in the React tree it is rendered. The `<head>` is the only valid place for `<meta>` to exist within the DOM, yet it’s convenient and keeps things composable if a component representing a specific page can render `<meta>` components itself. + +There is one exception to this: if `<meta>` has an [`itemProp`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/itemprop) prop, there is no special behavior, because in this case it doesn’t represent metadata about the document but rather metadata about a specific part of the page. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a --- @@ -54,7 +68,11 @@ React는 `<meta>` 컴포넌트가 React 트리 어디에서 렌더링되든 상 ### 문서에 메타데이터 추가하기 {/*annotating-the-document-with-metadata*/} +<<<<<<< HEAD 키워드, 요약 또는 저자의 이름과 같은 메타데이터를 문서에 추가할 수 있습니다. React는 해당 메타데이터를 문서 `<head>`에 배치하며, React 트리 내에서 어디에 렌더링되든 상관없이 해당 작업이 이루어집니다. +======= +You can annotate the document with metadata such as keywords, a summary, or the author’s name. React will place this metadata within the document `<head>` regardless of where in the React tree it is rendered. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```html <meta name="author" content="John Smith" /> @@ -85,7 +103,11 @@ export default function SiteMapPage() { ### 문서 내 특정 항목에 메타데이터 추가하기 {/*annotating-specific-items-within-the-document-with-metadata*/} +<<<<<<< HEAD `itemProp` Props와 함께 `<meta>` 컴포넌트를 사용하여 문서 내 특정 항목에 메타데이터를 추가할 수 있습니다. 이 경우, React는 이러한 주석을 문서 내 `<head>`에 배치하지 않고, 다른 React 컴포넌트처럼 배치합니다. +======= +You can use the `<meta>` component with the `itemProp` prop to annotate specific items within the document with metadata. In this case, React will *not* place these annotations within the document `<head>` but will place them like any other React component. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js <section itemScope> diff --git a/src/content/reference/react-dom/components/script.md b/src/content/reference/react-dom/components/script.md index 4db79734e..efd281de4 100644 --- a/src/content/reference/react-dom/components/script.md +++ b/src/content/reference/react-dom/components/script.md @@ -40,6 +40,7 @@ script: "<script>" 지원하는 다른 속성들: +<<<<<<< HEAD * `async`: 불리언 값. 브라우저가 문서의 남은 부분을 처리할 때까지 스크립트 실행을 연기할 수 있도록 합니다. 이는 성능을 위한 우선적인 동작 방식입니다. * `crossOrigin`: 문자열. 사용할 [CORS 정책](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin)입니다. 가능한 값은 `anonymous`와 `use-credentials`입니다. * `fetchPriority`: 문자열. 여러 스크립트를 동시에 가져올 때 브라우저가 스크립트를 우선순위로 순위 지정할 수 있도록 합니다. `"high"`, `"low"`, 또는 `"auto"` (기본값)일 수 있습니다. @@ -48,6 +49,16 @@ script: "<script>" * `nonce`: 문자열. 엄격한 콘텐츠 보안 정책을 사용할 때 [리소스를 허용하기 위해](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) 사용하는 암호화된 nonce입니다. * `referrer`: 문자열. 스크립트를 가져오고 스크립트가 다시 가져온 리소스를 가져올 때 보낼 [Referer 헤더를 지정합니다.](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#referrerpolicy) * `type`: 문자열. 스크립트가 [전통적인 스크립트, ES 모듈 또는 import 맵](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type)인지를 나타냅니다. +======= +* `async`: a boolean. Allows the browser to defer execution of the script until the rest of the document has been processed — the preferred behavior for performance. +* `crossOrigin`: a string. The [CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) to use. Its possible values are `anonymous` and `use-credentials`. +* `fetchPriority`: a string. Lets the browser rank scripts in priority when fetching multiple scripts at the same time. Can be `"high"`, `"low"`, or `"auto"` (the default). +* `integrity`: a string. A cryptographic hash of the script, to [verify its authenticity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). +* `noModule`: a boolean. Disables the script in browsers that support ES modules — allowing for a fallback script for browsers that do not. +* `nonce`: a string. A cryptographic [nonce to allow the resource](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) when using a strict Content Security Policy. +* `referrer`: a string. Says [what Referer header to send](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#referrerpolicy) when fetching the script and any resources that the script fetches in turn. +* `type`: a string. Says whether the script is a [classic script, ES module, or import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a React의 [스크립트 특수 처리](#special-rendering-behavior)를 비활성화하는 속성들: diff --git a/src/content/reference/react-dom/components/title.md b/src/content/reference/react-dom/components/title.md index 1a2303630..d3cbba02f 100644 --- a/src/content/reference/react-dom/components/title.md +++ b/src/content/reference/react-dom/components/title.md @@ -36,11 +36,19 @@ title: "<title>" #### 특별한 렌더링 동작 {/*special-rendering-behavior*/} +<<<<<<< HEAD React는 `<title>` 컴포넌트에 해당하는 DOM 요소를 React 트리 내 어디에서 렌더링하든 항상 문서의 `<head>` 내에 배치합니다. `<head>`는 DOM 내에서 `<title>`이 존재할 수 있는 유일한 위치이지만, 특정 페이지를 나타내는 컴포넌트가 자체적으로 `<title>`을 렌더링할 수 있으면 편리하고 구성 가능하게 유지됩니다. 여기에는 두 가지 예외가 있습니다. * `<title>`이 `<svg>` 컴포넌트 내에 있는 경우, 특별한 동작이 없습니다. 이 맥락에서는 문서의 제목을 나타내는 것이 아니라 [해당 SVG 그래픽에 대한 접근성 주석](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title)이기 때문입니다. * `<title>`에 [`itemProp`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/itemprop) 속성이 있는 경우, 특별한 동작이 없습니다. 이 경우 문서의 제목이 아니라 페이지의 특정 부분에 대한 메타데이터를 나타내기 때문입니다. +======= +React will always place the DOM element corresponding to the `<title>` component within the document’s `<head>`, regardless of where in the React tree it is rendered. The `<head>` is the only valid place for `<title>` to exist within the DOM, yet it’s convenient and keeps things composable if a component representing a specific page can render its `<title>` itself. + +There are two exception to this: +* If `<title>` is within an `<svg>` component, then there is no special behavior, because in this context it doesn’t represent the document’s title but rather is an [accessibility annotation for that SVG graphic](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title). +* If the `<title>` has an [`itemProp`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/itemprop) prop, there is no special behavior, because in this case it doesn’t represent the document’s title but rather metadata about a specific part of the page. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Pitfall> diff --git a/src/content/reference/react-dom/hooks/useFormStatus.md b/src/content/reference/react-dom/hooks/useFormStatus.md index 3a0617592..94e1dd514 100644 --- a/src/content/reference/react-dom/hooks/useFormStatus.md +++ b/src/content/reference/react-dom/hooks/useFormStatus.md @@ -40,7 +40,11 @@ export default function App() { } ``` +<<<<<<< HEAD 상태 정보를 제공받기 위해 `Submit` 컴포넌트를 `<form>` 내부에 렌더링해야 합니다. 이 Hook은 폼이 현재 제출하고 있는 상태인지를 의미하는 <CodeStep step={1}>`pending`</CodeStep> 프로퍼티와 같은 상태 정보를 반환합니다. +======= +To get status information, the `Submit` component must be rendered within a `<form>`. The Hook returns information like the <CodeStep step={1}>`pending`</CodeStep> property which tells you if the form is actively submitting. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 위의 예시에서 `Submit` 컴포넌트는 폼이 제출 중일 때 `<button>`을 누를 수 없도록 하기 위해 이 정보를 활용합니다. @@ -65,8 +69,13 @@ export default function App() { #### 주의 사항 {/*caveats*/} +<<<<<<< HEAD * `useFormStatus` Hook은 `<form>` 내부에 렌더링한 컴포넌트에서 호출해야 합니다. * `useFormStatus`는 오직 상위 `<form>`에 대한 상태 정보만 반환합니다. 동일한 컴포넌트나 자식 컴포넌트에서 렌더링한 `<form>`의 상태 정보는 반환하지 않습니다. +======= +* The `useFormStatus` Hook must be called from a component that is rendered inside a `<form>`. +* `useFormStatus` will only return status information for a parent `<form>`. It will not return status information for any `<form>` rendered in that same component or children components. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a --- @@ -75,7 +84,11 @@ export default function App() { ### 폼을 제출하는 동안 대기 중인 상태로 표시하기 {/*display-a-pending-state-during-form-submission*/} 폼을 제출하는 동안 대기<sup>Pending</sup> 상태를 표시하려면 `<form>` 내에서 렌더링한 컴포넌트에서 `useFormStatus` Hook을 호출하고 반환된 `pending` 프로퍼티를 확인하세요. +<<<<<<< HEAD 여기서는 `pending` 프로퍼티를 사용하여 폼이 제출 중인지를 나타냅니다. +======= +Here, we use the `pending` property to indicate the form is submitting. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Sandpack> @@ -131,7 +144,11 @@ function Form() { ```js function Submit() { +<<<<<<< HEAD // ✅ `pending`은 Submit 컴포넌트를 감싸는 폼에서 파생됩니다 +======= + // ✅ `pending` will be derived from the form that wraps the Submit component +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a const { pending } = useFormStatus(); return <button disabled={pending}>...</button>; } @@ -223,7 +240,11 @@ button { ### `status.pending`이 절대로 `true`가 되지 않습니다 {/*pending-is-never-true*/} +<<<<<<< HEAD `useFormStatus`는 오직 상위 `<form>`에 대한 상태 정보만 반환합니다. +======= +`useFormStatus` will only return status information for a parent `<form>`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a `useFormStatus`를 호출하는 컴포넌트가 `<form>`에 감싸져 있지 않다면, `status.pending`은 항상 `false`를 반환합니다. `useFormStatus`가 `<form>` 엘리먼트의 자식 컴포넌트에서 호출되는지 확인하세요. diff --git a/src/content/reference/react-dom/preconnect.md b/src/content/reference/react-dom/preconnect.md index c8972f033..a05746ae1 100644 --- a/src/content/reference/react-dom/preconnect.md +++ b/src/content/reference/react-dom/preconnect.md @@ -34,7 +34,11 @@ function AppRoot() { [아래 예시를 참고하세요.](#usage) +<<<<<<< HEAD `preconnect`는 브라우저가 해당 서버와 연결을 맺어야 한다는 힌트를 제공합니다. 브라우저가 해당 서버를 선택하면, 해당 서버에서 리소스를 불러오는 속도가 빨라질 수 있습니다. +======= +The `preconnect` function provides the browser with a hint that it should open a connection to the given server. If the browser chooses to do so, this can speed up the loading of resources from that server. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 매개변수 {/*parameters*/} diff --git a/src/content/reference/react-dom/prefetchDNS.md b/src/content/reference/react-dom/prefetchDNS.md index b18d439be..3fa5d743d 100644 --- a/src/content/reference/react-dom/prefetchDNS.md +++ b/src/content/reference/react-dom/prefetchDNS.md @@ -34,7 +34,11 @@ function AppRoot() { [아래 예시를 참고하세요.](#usage) +<<<<<<< HEAD `prefetchDNS`는 브라우저에게 주어진 서버의 IP 주소를 조회해야 한다는 힌트를 제공합니다. 브라우저가 이를 수행하기로 선택하면 해당 서버에서 리소스를 로딩하는 속도가 빨라질 수 있습니다. +======= +The prefetchDNS function provides the browser with a hint that it should look up the IP address of a given server. If the browser chooses to do so, this can speed up the loading of resources from that server. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 매개변수 {/*parameters*/} diff --git a/src/content/reference/react-dom/preinit.md b/src/content/reference/react-dom/preinit.md index eca5d4413..fee74805e 100644 --- a/src/content/reference/react-dom/preinit.md +++ b/src/content/reference/react-dom/preinit.md @@ -44,6 +44,7 @@ function AppRoot() { #### 매개변수 {/*parameters*/} +<<<<<<< HEAD * `href`: 문자열. 다운로드하고 실행할 리소스의 URL입니다. * `options`: 객체. 다음 속성들을 포함할 수 있습니다. * `as`: 필수 문자열. 리소스의 유형입니다. 가능한 값은 `script`와 `style`입니다. @@ -52,6 +53,16 @@ function AppRoot() { * `integrity`: 문자열. 리소스의 [무결성을 검증](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)하기 위한 암호화 해시입니다. * `nonce`: 문자열. 엄격한 콘텐츠 보안 정책을 사용할 때, 리소스를 허용하기 위한 암호화된 [nonce to allow the resource](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce)입니다. * `fetchPriority`: 문자열. 리소스를 가져오는 데 사용할 상대적인 우선순위를 제안합니다. 가능한 값은 `auto` (기본값), `high`, `low`입니다. +======= +* `href`: a string. The URL of the resource you want to download and execute. +* `options`: an object. It contains the following properties: + * `as`: a required string. The type of resource. Its possible values are `script` and `style`. + * `precedence`: a string. Required with stylesheets. Says where to insert the stylesheet relative to others. Stylesheets with higher precedence can override those with lower precedence. The possible values are `reset`, `low`, `medium`, `high`. + * `crossOrigin`: a string. The [CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) to use. Its possible values are `anonymous` and `use-credentials`. + * `integrity`: a string. A cryptographic hash of the resource, to [verify its authenticity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). + * `nonce`: a string. A cryptographic [nonce to allow the resource](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) when using a strict Content Security Policy. + * `fetchPriority`: a string. Suggests a relative priority for fetching the resource. The possible values are `auto` (the default), `high`, and `low`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 반환값 {/*returns*/} diff --git a/src/content/reference/react-dom/preinitModule.md b/src/content/reference/react-dom/preinitModule.md index d019373cb..d534a5f55 100644 --- a/src/content/reference/react-dom/preinitModule.md +++ b/src/content/reference/react-dom/preinitModule.md @@ -44,12 +44,21 @@ function AppRoot() { #### 매개변수 {/*parameters*/} +<<<<<<< HEAD * `href`: 문자열입니다. 다운로드하고 실행할 모듈의 URL입니다. * `options`: 객체입니다. 다음 속성을 포함합니다: * `as`: 필수 문자열입니다. 반드시 `'script'`여야 합니다. * `crossOrigin`: 문자열입니다. 사용할 [CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin)을 지정합니다. 가능한 값은 `anonymous` 또는 `use-credentials`입니다. * `integrity`: 문자열입니다. 모듈의 암호학적 해시로, [무결성을 검증](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)하는 데 사용됩니다. * `nonce`: 문자열입니다. 엄격한 Content Security Policy를 사용할 때 모듈을 허용하기 위한 암호학적 [nonce](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce)입니다. +======= +* `href`: a string. The URL of the module you want to download and execute. +* `options`: an object. It contains the following properties: + * `as`: a required string. It must be `'script'`. + * `crossOrigin`: a string. The [CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) to use. Its possible values are `anonymous` and `use-credentials`. + * `integrity`: a string. A cryptographic hash of the module, to [verify its authenticity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). + * `nonce`: a string. A cryptographic [nonce to allow the module](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) when using a strict Content Security Policy. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 반환값 {/*returns*/} diff --git a/src/content/reference/react-dom/preload.md b/src/content/reference/react-dom/preload.md index e4b9038eb..891563a5e 100644 --- a/src/content/reference/react-dom/preload.md +++ b/src/content/reference/react-dom/preload.md @@ -44,6 +44,7 @@ function AppRoot() { #### 매개변수 {/*parameters*/} +<<<<<<< HEAD * `href`: 문자열입니다. 다운로드하려는 리소스의 URL입니다. * `options`: 객체입니다. 여기에는 다음과 같은 속성이 포함되어 있습니다. * `as`: 필수 문자열입니다. 리소스의 타입입니다. [가능한 값](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#as)은 `audio`, `document`, `embed`, `fetch`, `font`, `image`, `object`, `script`, `style`, `track`, `video`, `worker`입니다. @@ -55,6 +56,19 @@ function AppRoot() { * `fetchPriority`: 문자열입니다. 리소스 페칭의 상대적 우선순위를 제안합니다. 사용할 수 있는 값은 `auto` (기본값), `high` 그리고 `low`입니다. * `imageSrcSet`: 문자열입니다. `as: "image"`와만 함께 사용합니다. [이미지의 소스 세트](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)를 지정합니다. * `imageSizes`: 문자열입니다. `as: "image"`와만 함께 사용합니다. [이미지의 크기](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)를 지정합니다. +======= +* `href`: a string. The URL of the resource you want to download. +* `options`: an object. It contains the following properties: + * `as`: a required string. The type of resource. Its [possible values](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#as) are `audio`, `document`, `embed`, `fetch`, `font`, `image`, `object`, `script`, `style`, `track`, `video`, `worker`. + * `crossOrigin`: a string. The [CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) to use. Its possible values are `anonymous` and `use-credentials`. It is required when `as` is set to `"fetch"`. + * `referrerPolicy`: a string. The [Referrer header](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#referrerpolicy) to send when fetching. Its possible values are `no-referrer-when-downgrade` (the default), `no-referrer`, `origin`, `origin-when-cross-origin`, and `unsafe-url`. + * `integrity`: a string. A cryptographic hash of the resource, to [verify its authenticity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). + * `type`: a string. The MIME type of the resource. + * `nonce`: a string. A cryptographic [nonce to allow the resource](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) when using a strict Content Security Policy. + * `fetchPriority`: a string. Suggests a relative priority for fetching the resource. The possible values are `auto` (the default), `high`, and `low`. + * `imageSrcSet`: a string. For use only with `as: "image"`. Specifies the [source set of the image](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images). + * `imageSizes`: a string. For use only with `as: "image"`. Specifies the [sizes of the image](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 반환값 {/*returns*/} diff --git a/src/content/reference/react-dom/preloadModule.md b/src/content/reference/react-dom/preloadModule.md index 245c09ef2..05d77a751 100644 --- a/src/content/reference/react-dom/preloadModule.md +++ b/src/content/reference/react-dom/preloadModule.md @@ -44,6 +44,7 @@ function AppRoot() { #### 매개변수 {/*parameters*/} +<<<<<<< HEAD * `href`: 문자열입니다. 다운로드하려는 모듈의 URL입니다. * `options`: 객체입니다. 여기에는 다음과 같은 속성들이 포함되어 있습니다. * `as`: 필수 문자열입니다. `'script'`여야 합니다. @@ -51,6 +52,14 @@ function AppRoot() { * `integrity`: 문자열입니다. 모듈의 [신뢰성 확인](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)을 위한 모듈의 암호화 해시입니다. * `nonce`: 문자열입니다. 엄격한 컨텐츠 보안 정책을 사용할 때 [모듈을 허용하기 위한 암호화 논스(Nonce)](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce)입니다. +======= +* `href`: a string. The URL of the module you want to download. +* `options`: an object. It contains the following properties: + * `as`: a required string. It must be `'script'`. + * `crossOrigin`: a string. The [CORS policy](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) to use. Its possible values are `anonymous` and `use-credentials`. + * `integrity`: a string. A cryptographic hash of the module, to [verify its authenticity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). + * `nonce`: a string. A cryptographic [nonce to allow the module](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) when using a strict Content Security Policy. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 반환값 {/*returns*/} diff --git a/src/content/reference/react-dom/server/renderToPipeableStream.md b/src/content/reference/react-dom/server/renderToPipeableStream.md index 5890c48a3..eab0ce2a8 100644 --- a/src/content/reference/react-dom/server/renderToPipeableStream.md +++ b/src/content/reference/react-dom/server/renderToPipeableStream.md @@ -294,7 +294,11 @@ Suspense는 Effect 또는 이벤트 핸들러 내부에서 데이터를 가져 `Posts` 컴포넌트에서 데이터를 불러오는 정확한 방법은 앞서 설명한 프레임워크에 따라 다릅니다. Suspense를 지원하는 프레임워크를 사용하는 경우, 데이터를 가져오는 자세한 방법은 해당 프레임워크 문서에서 찾을 수 있습니다. +<<<<<<< HEAD 독자적인 프레임워크를 사용하지 않는 Suspense 지원 데이터 가져오기는 아직 지원하지 않습니다. Suspense를 지원하는 데이터 소스를 구현하기 위한 요구 사항은 불안정하고 문서화되지 않았습니다. 데이터 소스를 Suspense와 통합하기 위한 공식 API는 React의 향후 버전에서 출시할 예정입니다. +======= +Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Note> diff --git a/src/content/reference/react-dom/server/renderToReadableStream.md b/src/content/reference/react-dom/server/renderToReadableStream.md index 03db97a2b..927f146d7 100644 --- a/src/content/reference/react-dom/server/renderToReadableStream.md +++ b/src/content/reference/react-dom/server/renderToReadableStream.md @@ -292,7 +292,11 @@ Suspense는 Effect 또는 이벤트 핸들러 내부에서 데이터를 가져 `Posts` 컴포넌트에서 데이터를 불러오는 정확한 방법은 앞서 설명한 프레임워크에 따라 다릅니다. Suspense를 지원하는 프레임워크를 이용하는 경우, 데이터를 가져오는 자세한 방법은 해당 프레임워크 문서에서 찾을 수 있습니다. +<<<<<<< HEAD 독자적인 프레임워크를 사용하지 않는 Suspense 지원 데이터 가져오기는 아직 지원하지 않습니다. Suspense를 지원하는 데이터 소스를 구현하기 위한 요구 사항은 불안정하고 문서화되지 않았습니다. 데이터 소스를 Suspense와 통합하기 위한 공식 API는 React의 향후 버전에서 출시할 예정입니다. +======= +Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Note> diff --git a/src/content/reference/react-dom/server/resume.md b/src/content/reference/react-dom/server/resume.md index 38c58710d..682c91174 100644 --- a/src/content/reference/react-dom/server/resume.md +++ b/src/content/reference/react-dom/server/resume.md @@ -77,7 +77,7 @@ async function handler(request, writable) { <Sandpack> -```js src/App.js hidden +```js src/App.js hidden ``` ```html public/index.html diff --git a/src/content/reference/react/Activity.md b/src/content/reference/react/Activity.md index 50b7c516e..f76882d0e 100644 --- a/src/content/reference/react/Activity.md +++ b/src/content/reference/react/Activity.md @@ -42,8 +42,13 @@ Activity 경계가 <CodeStep step={1}>숨겨지면</CodeStep>, React는 `display #### Props {/*props*/} +<<<<<<< HEAD * `children`: 표시하거나 숨길 UI입니다. * `mode`: `'visible'` 또는 `'hidden'` 중 하나의 문자열 값입니다. 생략하면 기본값은 `'visible'`입니다. +======= +* `children`: The UI you intend to show and hide. +* `mode`: A string value of either `'visible'` or `'hidden'`. If omitted, defaults to `'visible'`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 주의 사항 {/*caveats*/} @@ -111,7 +116,7 @@ import { useState } from 'react'; export default function Sidebar() { const [isExpanded, setIsExpanded] = useState(false) - + return ( <nav> <button onClick={() => setIsExpanded(!isExpanded)}> @@ -219,7 +224,7 @@ import { useState } from 'react'; export default function Sidebar() { const [isExpanded, setIsExpanded] = useState(false) - + return ( <nav> <button onClick={() => setIsExpanded(!isExpanded)}> @@ -287,7 +292,7 @@ Activity 경계는 `display: none`을 사용해 자식 컴포넌트를 숨기기 <Sandpack> -```js src/App.js +```js src/App.js import { useState } from 'react'; import TabButton from './TabButton.js'; import Home from './Home.js'; @@ -434,7 +439,7 @@ export default function Home() { } ``` -```js src/Contact.js +```js src/Contact.js export default function Contact() { return ( <div> @@ -765,7 +770,11 @@ Activity는 Effect 내부에서 가져온 데이터를 감지하지 **않습니 위의 `Posts` 컴포넌트에서 데이터를 로드하는 정확한 방법은 프레임워크에 따라 다릅니다. Suspense가 가능한 프레임워크를 사용하는 경우, 프레임워크의 데이터 불러오기 관련 문서에서 자세한 내용을 확인할 수 있습니다. +<<<<<<< HEAD 독자적인 프레임워크를 사용하지 않는 Suspense가 가능한 데이터 가져오기 기능은 아직 지원되지 않습니다. Suspense 지원 데이터 소스를 구현하기 위한 요구 사항은 불안정하고 문서화되지 않았습니다. 데이터 소스를 Suspense와 통합하기 위한 공식 API는 향후 React 버전에서 출시될 예정입니다. +======= +Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Note> @@ -903,7 +912,7 @@ function Page() { </Activity> </> ); -} +} ``` --- @@ -975,7 +984,7 @@ export default function Home() { } ``` -```js src/Video.js +```js src/Video.js export default function Video() { return ( <video @@ -1068,7 +1077,7 @@ export default function Home() { } ``` -```js src/Video.js +```js src/Video.js export default function Video() { return ( <video @@ -1185,7 +1194,7 @@ export default function Home() { } ``` -```js src/Video.js +```js src/Video.js import { useRef, useLayoutEffect } from 'react'; export default function Video() { @@ -1238,7 +1247,11 @@ video { width: 300px; margin-top: 10px; aspect-ratio: 16/9; } 하지만 일반적으로 대부분의 React 컴포넌트는 이미 Activity 경계에 의해 숨겨지는 것에 대해 견고해야 합니다. 개념적으로 "숨겨진" Activity는 마운트 해제된 것으로 생각해야 합니다. +<<<<<<< HEAD 적절한 클린업이 없는 다른 Effect를 미리 발견하려면 [`<StrictMode>`](/reference/react/StrictMode) 사용을 권장합니다. 이는 Activity 경계뿐만 아니라 React의 다른 많은 동작에도 중요합니다. +======= +To eagerly discover other Effects that don't have proper cleanup, which is important not only for Activity boundaries but for many other behaviors in React, we recommend using [`<StrictMode>`](/reference/react/StrictMode). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a --- @@ -1249,4 +1262,8 @@ video { width: 300px; margin-top: 10px; aspect-ratio: 16/9; } 컴포넌트의 부작용을 클린업하기 위해 Effect가 마운트되는 것에 의존하고 있다면, 대신 반환된 클린업 함수에서 작업을 수행하도록 Effect를 리팩터링하세요. +<<<<<<< HEAD 문제가 있는 Effect를 미리 찾으려면 [`<StrictMode>`](/reference/react/StrictMode) 추가를 권장합니다. 이는 예상치 못한 부작용을 포착하기 위해 Activity 마운트 해제와 마운트를 미리 수행합니다. +======= +To eagerly find problematic Effects, we recommend adding [`<StrictMode>`](/reference/react/StrictMode) which will eagerly perform Activity unmounts and mounts to catch any unexpected side-effects. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a diff --git a/src/content/reference/react/Children.md b/src/content/reference/react/Children.md index 470b75c69..61d4ee76c 100644 --- a/src/content/reference/react/Children.md +++ b/src/content/reference/react/Children.md @@ -492,7 +492,11 @@ export default function RowList({ children }) { ### `children` 배열로 병합하기 {/*converting-children-to-an-array*/} +<<<<<<< HEAD `Children.toArray(children)`는 `children` 데이터 구조를 일반적인 자바스크립트 배열로 변경합니다. 이것을 사용해서 [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), [`sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort), [`reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse)와 같은 배열의 내장 메서드를 조작할 수 있습니다. +======= +Call `Children.toArray(children)` to turn the `children` data structure into a regular JavaScript array. This lets you manipulate the array with built-in array methods like [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), [`sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort), or [`reverse`.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse) +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Sandpack> diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 3ab8867f6..adf9bdd61 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -724,7 +724,11 @@ React에 재렌더링을 건너뛸 수 있음을 알리려면 `false`를 반환 #### 주의 사항 {/*shouldcomponentupdate-caveats*/} +<<<<<<< HEAD - 이 메서드는 *오직* 성능 최적화를 위해서만 존재합니다. 이 메서드 없이 컴포넌트가 중단되는 경우 먼저 그 문제를 해결하세요. +======= +- This method *only* exists as a performance optimization. If your component breaks without it, fix that first. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a - `shouldComponentUpdate`를 직접 작성하는 대신 [`PureComponent`](/reference/react/PureComponent)를 사용하는 것을 고려하세요. `PureComponent`는 props와 state를 얕게(shallowly) 비교하여 필요한 업데이트를 건너뛸 가능성을 줄여줍니다. @@ -1275,7 +1279,7 @@ button { margin-left: 10px; } Error boundaries do not catch errors for: - Event handlers [(learn more)](/learn/responding-to-events) -- [Server side rendering](/reference/react-dom/server) +- [Server side rendering](/reference/react-dom/server) - Errors thrown in the error boundary itself (rather than its children) - Asynchronous code (e.g. `setTimeout` or `requestAnimationFrame` callbacks); an exception is the usage of the [`startTransition`](/reference/react/useTransition#starttransition) function returned by the [`useTransition`](/reference/react/useTransition) Hook. Errors thrown inside the transition function are caught by error boundaries [(learn more)](/reference/react/useTransition#displaying-an-error-to-users-with-error-boundary) diff --git a/src/content/reference/react/Fragment.md b/src/content/reference/react/Fragment.md index ff2e1cef2..1b065cbb9 100644 --- a/src/content/reference/react/Fragment.md +++ b/src/content/reference/react/Fragment.md @@ -4,7 +4,11 @@ title: <Fragment> (<>...</>) <Intro> +<<<<<<< HEAD `<Fragment>`는 `<>...</>` 문법으로 자주 사용되며, 래퍼 노드 없이 엘리먼트를 그룹화할 수 있게 해줍니다. +======= +`<Fragment>`, often used via `<>...</>` syntax, lets you group elements without a wrapper node. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Canary> Fragment는 `ref`를 받을 수도 있으며, 래퍼 엘리먼트를 추가하지 않고도 기본 DOM 노드와 상호작용할 수 있습니다. 아래 레퍼런스와 사용법을 참고하세요.</Canary> @@ -41,6 +45,7 @@ title: <Fragment> (<>...</>) - `removeEventListener(type, listener, options?)`: Fragment의 모든 최상위 DOM 자식에서 이벤트 리스너를 제거합니다. - `dispatchEvent(event)`: Fragment의 가상 자식에 이벤트를 디스패치하여 추가된 리스너를 호출하며, DOM 부모로 버블링될 수 있습니다. +<<<<<<< HEAD **레이아웃 메서드** - `compareDocumentPosition(otherNode)`: Fragment의 문서 위치를 다른 노드와 비교합니다. - Fragment에 자식이 있으면 네이티브 `compareDocumentPosition` 값이 반환됩니다. @@ -48,6 +53,15 @@ title: <Fragment> (<>...</>) - 포탈이나 다른 삽입으로 인해 React 트리와 DOM 트리에서 다른 관계를 가진 엘리먼트는 `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`입니다. - `getClientRects()`: 모든 자식의 경계 사각형을 나타내는 `DOMRect` 객체의 평탄화된 배열을 반환합니다. - `getRootNode()`: Fragment의 부모 DOM 노드를 포함하는 루트 노드를 반환합니다. +======= +**Layout methods:** +- `compareDocumentPosition(otherNode)`: Compares the document position of the Fragment with another node. + - If the Fragment has children, the native `compareDocumentPosition` value is returned. + - Empty Fragments will attempt to compare positioning within the React tree and include `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`. + - Elements that have a different relationship in the React tree and DOM tree due to portaling or other insertions are `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`. +- `getClientRects()`: Returns a flat array of `DOMRect` objects representing the bounding rectangles of all children. +- `getRootNode()`: Returns the root node containing the Fragment's parent DOM node. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a **포커스 관리 메서드** - `focus(options?)`: Fragment 내의 첫 번째 포커스 가능한 DOM 노드에 포커스합니다. 중첩된 자식에 대해 깊이 우선으로 포커스를 시도합니다. @@ -279,7 +293,7 @@ function VisibilityObserverFragment({ threshold = 0.5, onVisibilityChange, child }, { threshold } ); - + fragmentRef.current.observeUsing(observer); return () => fragmentRef.current.unobserveUsing(observer); }, [threshold, onVisibilityChange]); diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index bc383ee05..034d09e8b 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -215,7 +215,11 @@ Suspense는 Effect 또는 이벤트 핸들러 내부에서 가져오는 데이 위의 `Albums` 컴포넌트에서 데이터를 로딩하는 정확한 방법은 프레임워크마다 다릅니다. Suspense가 가능한 프레임워크를 사용하는 경우, 프레임워크의 데이터 불러오기 관련 문서에서 자세한 내용을 확인할 수 있습니다. +<<<<<<< HEAD 독단적인 프레임워크를 사용하지 않는 Suspense가 가능한 데이터 가져오기 기능은 아직 지원되지 않습니다. Suspense 지원 데이터 소스를 구현하기 위한 요구 사항은 불안정하고 문서화되지 않았습니다. 데이터 소스를 Suspense와 통합하기 위한 공식 API는 향후 React 버전에서 출시될 예정입니다. +======= +Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Note> @@ -877,7 +881,11 @@ input { margin: 10px; } </Sandpack> +<<<<<<< HEAD 일반적인 대체 UI 패턴은 목록들에 대한 업데이트를 <em>지연<sup>Defer</sup></em>하고 새 결과가 준비될 때까지 이전 결과를 계속 보여주는 것입니다. [`useDeferredValue`](/reference/react/useDeferredValue) Hook을 사용하면 쿼리의 지연된 버전을 아래로 전달할 수 있습니다. +======= +A common alternative UI pattern is to *defer* updating the list and to keep showing the previous results until the new results are ready. The [`useDeferredValue`](/reference/react/useDeferredValue) Hook lets you pass a deferred version of the query down: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js {3,11} export default function App() { diff --git a/src/content/reference/react/ViewTransition.md b/src/content/reference/react/ViewTransition.md index 13f758b36..00582d3db 100644 --- a/src/content/reference/react/ViewTransition.md +++ b/src/content/reference/react/ViewTransition.md @@ -82,7 +82,14 @@ React는 내부적으로 `startViewTransition`을 자체적으로 호출하므 * **optional** `default`: 문자열 또는 객체. 다른 일치하는 활성화 프로퍼티가 없을 때 사용되는 [View Transition 클래스](#view-transition-class)입니다. * **optional** `name`: 문자열 또는 객체. 공유 엘리먼트 transition에 사용되는 View Transition의 이름입니다. 제공되지 않으면 React는 예상치 못한 애니메이션을 방지하기 위해 각 View Transition에 대해 고유한 이름을 사용합니다. +<<<<<<< HEAD #### 콜백 {/*events*/} +======= +- Only use `name` for [shared element transitions](#animating-a-shared-element). For all other animations, React automatically generates a unique name to prevent unexpected animations. +- By default, `setState` updates immediately and does not activate `<ViewTransition>`, only updates wrapped in a [Transition](/reference/react/useTransition), [`<Suspense>`](/reference/react/Suspense), or `useDeferredValue` activate ViewTransition. +- `<ViewTransition>` creates an image that can be moved around, scaled and cross-faded. Unlike Layout Animations you may have seen in React Native or Motion, this means that not every individual Element inside of it animates its position. This can lead to better performance and a more continuous feeling, smooth animation compared to animating every individual piece. However, it can also lose continuity in things that should be moving by themselves. So you might have to add more `<ViewTransition>` boundaries manually as a result. +- Currently, `<ViewTransition>` only works in the DOM. We're working on adding support for React Native and other platforms. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 이 콜백을 사용하면 [animate](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) API를 사용하여 애니메이션을 명령적으로 조정할 수 있습니다. @@ -113,7 +120,130 @@ View Transition 클래스는 ViewTransition이 활성화될 때 Transition 중 `<ViewTransition>`의 애니메이션을 커스터마이즈하려면 활성화 프로퍼티 중 하나에 View Transition 클래스를 제공할 수 있습니다. View Transition 클래스는 ViewTransition이 활성화될 때 React가 자식 엘리먼트에 적용하는 CSS 클래스 이름입니다. +<<<<<<< HEAD 예를 들어 "enter" 애니메이션을 커스터마이즈하려면 `enter` 프로퍼티에 클래스 이름을 제공합니다. +======= +`<ViewTransition>` provides props to define what animations trigger: + +```js +<ViewTransition + default="none" + enter="slide-up" + exit="slide-down" +/> +``` + +#### Props {/*view-transition-class-props*/} + +- **optional** `enter`: `"auto"`, `"none"`, a string, or an object. +- **optional** `exit`: `"auto"`, `"none"`, a string, or an object. +- **optional** `update`: `"auto"`, `"none"`, a string, or an object. +- **optional** `share`: `"auto"`, `"none"`, a string, or an object. +- **optional** `default`: `"auto"`, `"none"`, a string, or an object. + +#### Caveats {/*view-transition-class-caveats*/} + +- If `default` is `"none"` then all other triggers are turned off unless explicitly listed. + +#### Values {/*view-transition-values*/} + +View Transition class values can be: +- `auto`: the default. Uses the browser default animation. +- `none`: disable animations for this type. +- `<classname>`: a custom CSS class name to use for [customizing View Transitions](#styling-view-transitions). + +Object values can be an object with string keys and a value of `auto`, `none` or a custom className: +- `{[type]: value}`: applies `value` if the animation matches the [Transition Type](/reference/react/addTransitionType). +- `{default: value}`: the default value to apply if no [Transition Type](/reference/react/addTransitionType) is matched. + +For example, you can define a ViewTransition as: + +```js +<ViewTransition + /* turn off any animation not defined below */ + default="none" + enter={{ + /* apply slide-in for Transition Type `forward` */ + "forward": 'slide-in', + /* otherwise use the browser default animation */ + "default": 'auto' + }} + /* use the browser default for exit animations*/ + exit="auto" + /* apply a custom `cross-fade` class for updates */ + update="cross-fade" +> +``` + +See [Styling View Transitions](#styling-view-transitions) for how to define CSS classes for custom animations. + +--- + +### View Transition Event {/*view-transition-event*/} + +View Transition Events allow you to control the animation with JavaScript using the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API): + +```js +<ViewTransition + onEnter={instance => {/* ... */}} + onExit={instance => {/* ... */}} +/> +``` + +#### Props {/*view-transition-event-props*/} + +- **optional** `onEnter`: Called when an "enter" animation is triggered. +- **optional** `onExit`: Called when an "exit" animation is triggered. +- **optional** `onShare`: Called when a "share" animation is triggered. +- **optional** `onUpdate`: Called when an "update" animation is triggered. + + +#### Caveats {/*view-transition-event-caveats*/} +- Only one event fires per `<ViewTransition>` per Transition. `onShare` takes precedence over `onEnter` and `onExit`. +- Each event should return a **cleanup function**. The cleanup function is called when the View Transition finishes, allowing you to cancel or cleanup any animations. + +#### Arguments {/*view-transition-event-arguments*/} + +Each event receives two arguments: + +- `instance`: A View Transition instance that provides access to the view transition [pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API/Using#the_view_transition_process) + - `old`: The `::view-transition-old` pseudo-element. + - `new`: The `::view-transition-new` pseudo-element. + - `name`: The `view-transition-name` string for this boundary. + - `group`: The `::view-transition-group` pseudo-element. + - `imagePair`: The `::view-transition-image-pair` pseudo-element. +- `types`: An `Array<string>` of [Transition Types](/reference/react/addTransitionType) included in the animation. Empty array if no types were specified. + +For example, you can define a `onEnter` event that drives the animation using JavaScript: + +```js +<ViewTransition + onEnter={(instance, types) => { + const anim = instance.new.animate([{opacity: 0}, {opacity: 1}], { + duration: 500, + }); + return () => anim.cancel(); + }}> + <div>...</div> +</ViewTransition> +``` + +See [Animating with JavaScript](#animating-with-javascript) for more examples. + +--- + +## Styling View Transitions {/*styling-view-transitions*/} + +<Note> + +In many early examples of View Transitions around the web, you'll have seen using a [`view-transition-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/view-transition-name) and then style it using `::view-transition-...(my-name)` selectors. We don't recommend that for styling. Instead, we normally recommend using a View Transition Class instead. + +</Note> + +To customize the animation for a `<ViewTransition>` you can provide a View Transition Class to one of the activation props. The View Transition Class is a CSS class name that React applies to the child elements when the ViewTransition activates. + +For example, to customize an "enter" animation, provide a class name to the `enter` prop: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js <ViewTransition enter="slide-in"> @@ -336,7 +466,15 @@ button:hover { <Pitfall> +<<<<<<< HEAD `<ViewTransition>`은 DOM 노드보다 앞에 배치되어야만 활성화됩니다. `Child`가 다음과 같다면 애니메이션이 발생하지 않습니다. +======= +#### Only top-level ViewTransitions animate on exit/enter {/*only-top-level-viewtransition-animates-on-exit-enter*/} + +`<ViewTransition>` only activates exit/enter if it is placed _before_ any DOM nodes. + +If there's a `<div>` above `<ViewTransition>`, no exit/enter animations trigger: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js [3, 5] function Item() { @@ -2078,13 +2216,494 @@ button:hover { 스크롤 복원이 애니메이션 중에 정상적으로 동작하도록, React는 대기 중인 내비게이션이 완료될 때까지 기다립니다. 네비게이션이 React에서 차단되는 경우 `useEffect`는 교착 상태로 이어질 수 있으므로 라우터는 `useLayoutEffect`에서 차단을 해제해야 합니다. +<<<<<<< HEAD "뒤로" 네비게이션 중처럼 레거시 popstate 이벤트에서 `startTransition`이 시작되면 스크롤과 폼 복원이 올바르게 작동하도록 동기적으로 완료되어야 합니다. 이는 View Transition 애니메이션 실행과 충돌합니다. 따라서 React는 popstate에서 애니메이션을 건너뜁니다. 따라서 뒤로 버튼에 대해서는 애니메이션이 실행되지 않습니다. Navigation API를 사용하도록 라우터를 업그레이드하여 이를 해결할 수 있습니다. +======= +While [View Transition Classes](#view-transition-class) let you define animations with CSS, sometimes you need imperative control over the animation. The `onEnter`, `onExit`, `onUpdate`, and `onShare` callbacks give you direct access to the view transition pseudo-elements so you can animate them using the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API). + +Each callback receives an `instance` with `.old` and `.new` properties representing the view transition pseudo-elements. You can call `.animate()` on them just like you would on a DOM element: + +```js +<ViewTransition + onEnter={(instance) => { + const anim = instance.new.animate( + [ + {transform: 'scale(0.8)'}, + {transform: 'scale(1)'}, + ], + {duration: 300, easing: 'ease-out'} + ); + return () => anim.cancel(); + }}> + <div>...</div> +</ViewTransition> +``` + +This allows you to combine CSS-driven animations and JavaScript-driven animations. + +In the following example, the default cross-fade is handled by CSS, and the slide animations are driven by JavaScript in the `onEnter` and `onExit` animations: + +<Sandpack> + +```js src/Video.js hidden +function Thumbnail({video, children}) { + return ( + <div + aria-hidden="true" + tabIndex={-1} + className={`thumbnail ${video.image}`} + /> + ); +} + +export function Video({video}) { + return ( + <div className="video"> + <div className="link"> + <Thumbnail video={video}></Thumbnail> + + <div className="info"> + <div className="video-title">{video.title}</div> + <div className="video-description">{video.description}</div> + </div> + </div> + </div> + ); +} +``` + +```js +import {ViewTransition, useState, startTransition} from 'react'; +import {Video} from './Video'; +import videos from './data'; +import {SLIDE_IN, SLIDE_OUT} from './animations'; + +function Item() { + return ( + <ViewTransition + default="none" + /* CSS driven cross fade defaults */ + enter="auto" + exit="auto" + /* JS driven slide animations */ + onEnter={(instance) => { + const anim = instance.new.animate( + SLIDE_IN, + {duration: 500, easing: 'ease-out'} + ); + return () => anim.cancel(); + }} + onExit={(instance) => { + const anim = instance.old.animate( + SLIDE_OUT, + {duration: 300, easing: 'ease-in'} + ); + return () => anim.cancel(); + }}> + <Video video={videos[0]} /> + </ViewTransition> + ); +} + +export default function Component() { + const [showItem, setShowItem] = useState(false); + return ( + <> + <button + onClick={() => { + startTransition(() => { + setShowItem((prev) => !prev); + }); + }}> + {showItem ? '➖' : '➕'} + </button> + + {showItem ? <Item /> : null} + </> + ); +} +``` + +```js src/animations.js +export const SLIDE_IN = [ + {transform: 'translateY(20px)'}, + {transform: 'translateY(0)'}, +]; + +export const SLIDE_OUT = [ + {transform: 'translateY(0)'}, + {transform: 'translateY(-20px)'}, +]; +``` + +```js src/data.js hidden +export default [ + { + id: '1', + title: 'First video', + description: 'Video description', + image: 'blue', + }, +]; +``` + +```css +#root { + display: flex; + flex-direction: column; + align-items: center; + min-height: 200px; +} +button { + border: none; + border-radius: 50%; + width: 50px; + height: 50px; + display: flex; + justify-content: center; + align-items: center; + background-color: #f0f8ff; + color: white; + font-size: 20px; + cursor: pointer; + transition: background-color 0.3s, border 0.3s; +} +button:hover { + border: 2px solid #ccc; + background-color: #e0e8ff; +} +.thumbnail { + position: relative; + aspect-ratio: 16 / 9; + display: flex; + overflow: hidden; + flex-direction: column; + justify-content: center; + align-items: center; + border-radius: 0.5rem; + outline-offset: 2px; + width: 8rem; + vertical-align: middle; + background-color: #ffffff; + background-size: cover; + user-select: none; +} +.thumbnail.blue { + background-image: conic-gradient(at top right, #c76a15, #087ea4, #2b3491); +} +.video { + display: flex; + flex-direction: row; + gap: 0.75rem; + align-items: center; + margin-top: 1em; +} +.video .link { + display: flex; + flex-direction: row; + flex: 1 1 0; + gap: 0.125rem; + outline-offset: 4px; + cursor: pointer; +} +.video .info { + display: flex; + flex-direction: column; + justify-content: center; + margin-left: 8px; + gap: 0.125rem; +} +.video .info:hover { + text-decoration: underline; +} +.video-title { + font-size: 15px; + line-height: 1.25; + font-weight: 700; + color: #23272f; +} +.video-description { + color: #5e687e; + font-size: 13px; +} + +``` + +```json package.json hidden +{ + "dependencies": { + "react": "canary", + "react-dom": "canary", + "react-scripts": "latest" + } +} +``` + +</Sandpack> + +<Note> + +#### Always clean up View Transition Events {/*always-clean-up-view-transition-events*/} + +View Transition Events should always return a cleanup function: + +```js {7} +<ViewTransition + onEnter={(instance) => { + const anim = instance.new.animate( + SLIDE_IN, + {duration: 500, easing: 'ease-out'} + ); + return () => anim.cancel(); + }} +> +``` + +This allows the browser to cancel the animation when the View Transition is interrupted. + +</Note> +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a --- ## 문제 해결 {/*troubleshooting*/} +<<<<<<< HEAD ### `<ViewTransition>`이 활성화되지 않습니다 {/*my-viewtransition-is-not-activating*/} +======= +You can use `types` passed to `ViewTransition` events to conditionally apply different animations based on how the Transition was triggered. + +```js {3} + <ViewTransition + onEnter={(instance, types) => { + const duration = types.includes('fast') ? 150 : 2000; + const anim = instance.new.animate( + SLIDE_IN, + {duration: duration, easing: 'ease-out'} + ); + return () => anim.cancel(); + }} +> +``` + +This example calls [`addTransitionType`](/reference/react/addTransitionType) to mark a Transition as "fast" and then adjust the animation duration: + +<Sandpack> + +```js src/Video.js hidden +function Thumbnail({video, children}) { + return ( + <div + aria-hidden="true" + tabIndex={-1} + className={`thumbnail ${video.image}`} + /> + ); +} + +export function Video({video}) { + return ( + <div className="video"> + <div className="link"> + <Thumbnail video={video}></Thumbnail> + + <div className="info"> + <div className="video-title">{video.title}</div> + <div className="video-description">{video.description}</div> + </div> + </div> + </div> + ); +} +``` + +```js +import {ViewTransition, useState, startTransition, addTransitionType} from 'react'; +import {Video} from './Video'; +import videos from './data'; +import {SLIDE_IN, SLIDE_OUT} from './animations'; + +function Item() { + return ( + <ViewTransition + onEnter={(instance, types) => { + const duration = types.includes('fast') ? 150 : 2000; + const anim = instance.new.animate( + SLIDE_IN, + {duration: duration, easing: 'ease-out'} + ); + return () => anim.cancel(); + }} + onExit={(instance, types) => { + const duration = types.includes('fast') ? 150 : 500; + const anim = instance.old.animate( + SLIDE_OUT, + {duration: duration, easing: 'ease-in'} + ); + return () => anim.cancel(); + }}> + <Video video={videos[0]} /> + </ViewTransition> + ); +} + +export default function Component() { + const [showItem, setShowItem] = useState(false); + const [isFast, setIsFast] = useState(false); + return ( + <> + <div> + Fast: <input type="checkbox" onChange={() => {setIsFast(f => !f)}} value={isFast}></input> + </div><br /> + <button + onClick={() => { + startTransition(() => { + if (isFast) { + addTransitionType('fast'); + } + setShowItem((prev) => !prev); + }); + }}> + {showItem ? '➖' : '➕'} + </button> + + {showItem ? <Item /> : null} + </> + ); +} +``` + +```js src/animations.js +export const SLIDE_IN = [ + {opacity: 0, transform: 'translateY(20px)'}, + {opacity: 1, transform: 'translateY(0)'}, +]; + +export const SLIDE_OUT = [ + {opacity: 1, transform: 'translateY(0)'}, + {opacity: 0, transform: 'translateY(-20px)'}, +]; +``` + +```js src/data.js hidden +export default [ + { + id: '1', + title: 'First video', + description: 'Video description', + image: 'blue', + }, +]; +``` + +```css +#root { + display: flex; + flex-direction: column; + align-items: center; + min-height: 200px; +} +button { + border: none; + border-radius: 50%; + width: 50px; + height: 50px; + display: flex; + justify-content: center; + align-items: center; + background-color: #f0f8ff; + color: white; + font-size: 20px; + cursor: pointer; + transition: background-color 0.3s, border 0.3s; +} +button:hover { + border: 2px solid #ccc; + background-color: #e0e8ff; +} +.thumbnail { + position: relative; + aspect-ratio: 16 / 9; + display: flex; + overflow: hidden; + flex-direction: column; + justify-content: center; + align-items: center; + border-radius: 0.5rem; + outline-offset: 2px; + width: 8rem; + vertical-align: middle; + background-color: #ffffff; + background-size: cover; + user-select: none; +} +.thumbnail.blue { + background-image: conic-gradient(at top right, #c76a15, #087ea4, #2b3491); +} +.video { + display: flex; + flex-direction: row; + gap: 0.75rem; + align-items: center; + margin-top: 1em; +} +.video .link { + display: flex; + flex-direction: row; + flex: 1 1 0; + gap: 0.125rem; + outline-offset: 4px; + cursor: pointer; +} +.video .info { + display: flex; + flex-direction: column; + justify-content: center; + margin-left: 8px; + gap: 0.125rem; +} +.video .info:hover { + text-decoration: underline; +} +.video-title { + font-size: 15px; + line-height: 1.25; + font-weight: 700; + color: #23272f; +} +.video-description { + color: #5e687e; + font-size: 13px; +} + +``` + +```json package.json hidden +{ + "dependencies": { + "react": "canary", + "react-dom": "canary", + "react-scripts": "latest" + } +} +``` + +</Sandpack> + +--- + +### Building View Transition enabled routers {/*building-view-transition-enabled-routers*/} + +React waits for any pending Navigation to finish to ensure that scroll restoration happens within the animation. If the Navigation is blocked on React, your router must unblock in `useLayoutEffect` since `useEffect` would lead to a deadlock. + +If a `startTransition` is started from the legacy popstate event, such as during a "back"-navigation then it must finish synchronously to ensure scroll and form restoration works correctly. This is in conflict with running a View Transition animation. Therefore, React will skip animations from popstate and animations won't run for the back button. You can fix this by upgrading your router to use the Navigation API. + +--- + +## Troubleshooting {/*troubleshooting*/} + +### My `<ViewTransition>` is not activating {/*my-viewtransition-is-not-activating*/} +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a `<ViewTransition>` only activates if it is placed before any DOM node: diff --git a/src/content/reference/react/act.md b/src/content/reference/react/act.md index 44e3b8bed..60b297193 100644 --- a/src/content/reference/react/act.md +++ b/src/content/reference/react/act.md @@ -97,7 +97,11 @@ it('can render and update a counter', async () => { container = document.createElement('div'); document.body.appendChild(container); +<<<<<<< HEAD // ✅ 컴포넌트를 act() 안에서 렌더링합니다. +======= + // ✅ Render the component inside act(). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a await act(() => { ReactDOMClient.createRoot(container).render(<Counter />); }); @@ -130,7 +134,11 @@ it.only('can render and update a counter', async () => { ReactDOMClient.createRoot(container).render(<Counter />); }); +<<<<<<< HEAD // ✅ 이벤트 디스패치를 act() 안에서 실행합니다. +======= + // ✅ Dispatch the event inside act(). +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a await act(async () => { button.dispatchEvent(new MouseEvent('click', { bubbles: true })); }); diff --git a/src/content/reference/react/addTransitionType.md b/src/content/reference/react/addTransitionType.md index e7578b388..6937dc242 100644 --- a/src/content/reference/react/addTransitionType.md +++ b/src/content/reference/react/addTransitionType.md @@ -5,7 +5,11 @@ version: canary <Canary> +<<<<<<< HEAD **`addTransitionType` API는 현재 React의 카나리 및 실험적 채널에서만 사용할 수 있습니다.** +======= +**The `addTransitionType` API is currently only available in React’s Canary and Experimental channels.** +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a [React의 배포 채널에 대해 더 알아보세요.](/community/versioning-policy#all-release-channels) @@ -74,9 +78,15 @@ function Submit({action) { 현재 트랜지션 타입은 원인에 따라 서로 다른 애니메이션을 커스터마이즈하는 데 사용할 수 있습니다. 사용할 수 있는 방식은 세 가지입니다. +<<<<<<< HEAD - [브라우저 View Transition 타입으로 애니메이션 커스텀하기](#customize-animations-using-browser-view-transition-types) - [`View Transition` 클래스로 애니메이션 커스텀하기](#customize-animations-using-view-transition-class) - [`ViewTransition`이벤트로 애니메이션 커스텀하기](#customize-animations-using-viewtransition-events) +======= +- [Customize animations using browser view transition types](#customize-animations-using-browser-view-transition-types) +- [Customize animations using `View Transition` Class](#customize-animations-using-view-transition-class) +- [Customize animations using `ViewTransition` events](#customize-animations-using-viewtransition-events) +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 향후에는 트랜지션의 원인을 활용할 수 있는 다양한 용례를 지원할 예정입니다. diff --git a/src/content/reference/react/captureOwnerStack.md b/src/content/reference/react/captureOwnerStack.md index cd81e0896..0e0174be2 100644 --- a/src/content/reference/react/captureOwnerStack.md +++ b/src/content/reference/react/captureOwnerStack.md @@ -257,7 +257,7 @@ pre.nowrap { } .hidden { - display: none; + display: none; } ``` diff --git a/src/content/reference/react/cloneElement.md b/src/content/reference/react/cloneElement.md index 12625577b..c1c25d34a 100644 --- a/src/content/reference/react/cloneElement.md +++ b/src/content/reference/react/cloneElement.md @@ -246,7 +246,11 @@ button { ### 렌더링 prop으로 데이터를 전달하기 {/*passing-data-with-a-render-prop*/} +<<<<<<< HEAD `cloneElement`를 사용하는 대신에 `renderItem`과 같은 *렌더링 prop*을 사용하는 것을 고려해 보세요. 다음 예시의 `List`는 `renderItem`을 prop으로 받습니다. `List`는 모든 item에 대해 `renderItem`을 호출하고 `isHighlighted`를 인자로 전달합니다. +======= +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: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js {1,7} export default function List({ items, renderItem }) { diff --git a/src/content/reference/react/createContext.md b/src/content/reference/react/createContext.md index 9168fd9d1..f6fddd006 100644 --- a/src/content/reference/react/createContext.md +++ b/src/content/reference/react/createContext.md @@ -65,7 +65,11 @@ function App() { <Note> +<<<<<<< HEAD React 19부터는 `<SomeContext>`를 제공자<sup>Provider</sup>로 렌더링 할 수 있습니다. +======= +Starting in React 19, you can render `<SomeContext>` as a provider. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 오래된 React 버전은 `<SomeContext.Provider>`를 사용합니다. diff --git a/src/content/reference/react/experimental_taintUniqueValue.md b/src/content/reference/react/experimental_taintUniqueValue.md index c5fb7c513..ceb794318 100644 --- a/src/content/reference/react/experimental_taintUniqueValue.md +++ b/src/content/reference/react/experimental_taintUniqueValue.md @@ -77,7 +77,11 @@ experimental_taintUniqueValue( ### 토큰이 클라이언트 구성 요소로 전달되지 않도록 방지하기 {/*prevent-a-token-from-being-passed-to-client-components*/} +<<<<<<< HEAD 패스워드, 세션 토큰 또는 기타 고유 값과 같은 민감한 정보가 실수로 클라이언트 컴포넌트로 전달되지 않도록 `taintUniqueValue` 함수는 보호 레이어을 제공합니다. 값이 오염되면 클라이언트 컴포넌트로 전달하려는 시도는 오류를 발생시킵니다. +======= +To ensure that sensitive information such as passwords, session tokens, or other unique values do not inadvertently get passed to Client Components, the `taintUniqueValue` function provides a layer of protection. When a value is tainted, any attempt to pass it to a Client Component will result in an error. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a `lifetime` 인자는 값이 오염된 상태로 남아 있는 기간을 정의합니다. 오염된 상태로 무기한 유지되어야 하는 값의 경우 [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) 또는 `process`와 같은 객체가 `lifetime` 인자로 사용될 수 있습니다. 이 객체들은 앱이 실행되는 전체 기간을 수명으로 가집니다. @@ -178,8 +182,13 @@ export function fetchAPI(url) { } ``` +<<<<<<< HEAD 때때로 리팩토링 중에 실수가 발생할 수도 있으며 이것에 대해서 잘 모르는 동료가 있을 수도 있습니다. 이러한 실수를 방지하기 위해서 실제 패스워드를 "오염"시킬 수 있습니다. +======= +Sometimes mistakes happen during refactoring and not all of your colleagues might know about this. +To protect against this mistakes happening down the line we can "taint" the actual password: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js import "server-only"; diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 0c3ea03cb..41877a06c 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -453,7 +453,11 @@ function MessageComponent({messagePromise}) { ```jsx function MessageComponent({messagePromise}) { +<<<<<<< HEAD // ✅ `use`를 컴포넌트에서 호출하고 있습니다. +======= + // ✅ `use` is being called from a component. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a const message = use(messagePromise); // ... ``` diff --git a/src/content/reference/react/useActionState.md b/src/content/reference/react/useActionState.md index f886ab8a4..2145923dc 100644 --- a/src/content/reference/react/useActionState.md +++ b/src/content/reference/react/useActionState.md @@ -60,6 +60,10 @@ function StatefulForm({}) { 2. `form` 컴포넌트의 `action` Prop이나, 폼 내부 `button` 컴포넌트의 `formAction` Prop에 전달할 수 있는 새 액션입니다. 이 액션은 [`startTransition`](/reference/react/startTransition) 내에서 수동으로 호출할 수도 있습니다. 3. 현재 Transition이 대기 중인지 알려주는 `isPending` 플래그입니다. +<<<<<<< HEAD +======= +`dispatchAction` must be called from an Action. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 주의 사항 {/*caveats*/} @@ -72,7 +76,59 @@ function StatefulForm({}) { ### 폼 액션에서 반환된 정보 사용하기 {/*using-information-returned-by-a-form-action*/} +<<<<<<< HEAD 컴포넌트의 최상위 레벨에서 `useActionState`를 호출하면, 폼이 마지막으로 제출되었을 때 액션이 반환한 값에 접근할 수 있습니다. +======= +Unlike reducers in `useReducer`, the `reducerAction` can be async and perform side effects: + +```js +async function reducerAction(previousState, actionPayload) { + const newState = await post(actionPayload); + return newState; +} +``` + +Each time you call `dispatchAction`, React calls the `reducerAction` with the `actionPayload`. The reducer will perform side effects such as posting data, and return the new state. If `dispatchAction` is called multiple times, React queues and executes them in order so the result of the previous call is passed as `previousState` for the current call. + +#### Parameters {/*reduceraction-parameters*/} + +* `previousState`: The last state. Initially this is equal to the `initialState`. After the first call to `dispatchAction`, it's equal to the last state returned. + +* **optional** `actionPayload`: The argument passed to `dispatchAction`. It can be a value of any type. Similar to `useReducer` conventions, it is usually an object with a `type` property identifying it and, optionally, other properties with additional information. + +#### Returns {/*reduceraction-returns*/} + +`reducerAction` returns the new state, and triggers a Transition to re-render with that state. + +#### Caveats {/*reduceraction-caveats*/} + +* `reducerAction` can be sync or async. It can perform sync actions like showing a notification, or async actions like posting updates to a server. +* `reducerAction` is not invoked twice in `<StrictMode>` since `reducerAction` is designed to allow side effects. +* The return type of `reducerAction` must match the type of `initialState`. If TypeScript infers a mismatch, you may need to explicitly annotate your state type. +* If you set state after `await` in the `reducerAction` you currently need to wrap the state update in an additional `startTransition`. See the [startTransition](/reference/react/useTransition#react-doesnt-treat-my-state-update-after-await-as-a-transition) docs for more info. +* When using Server Functions, `actionPayload` needs to be [serializable](/reference/rsc/use-server#serializable-parameters-and-return-values) (values like plain objects, arrays, strings, and numbers). + +<DeepDive> + +#### Why is it called `reducerAction`? {/*why-is-it-called-reduceraction*/} + +The function passed to `useActionState` is called a *reducer action* because: + +- It *reduces* the previous state into a new state, like `useReducer`. +- It's an *Action* because it's called inside a Transition and can perform side effects. + +Conceptually, `useActionState` is like `useReducer`, but you can do side effects in the reducer. + +</DeepDive> + +--- + +## Usage {/*usage*/} + +### Adding state to an Action {/*adding-state-to-an-action*/} + +Call `useActionState` at the top level of your component to create state for the result of an Action. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js [[1, 7, "count"], [2, 7, "dispatchAction"], [3, 7, "isPending"]] import { useActionState } from 'react'; @@ -786,7 +842,7 @@ import Total from './Total'; export default function Checkout() { const abortRef = useRef(null); const [count, dispatchAction, isPending] = useActionState(updateCartAction, 0); - + async function addAction() { if (abortRef.current) { abortRef.current.abort(); @@ -1182,7 +1238,7 @@ When used with a [Server Function](/reference/rsc/server-functions), `useActionS </RSC> -See the [`<form>`](/reference/react-dom/components/form#handle-form-submission-with-a-server-function) docs for more information on using Actions with forms. +See the [`<form>`](/reference/react-dom/components/form#handle-form-submission-with-a-server-function) docs for more information on using Actions with forms. --- @@ -1210,16 +1266,16 @@ function Checkout() { // Return the error from the API as state return {...prevState, error: `Could not add quanitiy ${quantity}: ${result.error}`}; } - + if (!isPending) { // Clear the error state for the first dispatch. - return {count: result.count, error: null}; + return {count: result.count, error: null}; } - + // Return the new count, and any errors that happened. return {count: result.count, error: prevState.error}; - - + + }, { count: 0, diff --git a/src/content/reference/react/useEffect.md b/src/content/reference/react/useEffect.md index 3529646b3..69078b300 100644 --- a/src/content/reference/react/useEffect.md +++ b/src/content/reference/react/useEffect.md @@ -44,7 +44,13 @@ function ChatRoom({ roomId }) { #### 매개변수 {/*parameters*/} +<<<<<<< HEAD + `setup(설정)`: Effect의 로직이 포함된 함수입니다. 설정 함수는 선택적으로 *clean up(정리)* 함수를 반환할 수 있습니다. React는 컴포넌트가 DOM에 추가된 이후에 설정 함수를 실행합니다. 의존성의 변화에 따라 컴포넌트가 리렌더링이 되었을 경우, (설정 함수에 정리 함수를 추가했었다면) React는 이전 렌더링에 사용된 값으로 정리 함수를 실행한 후 새로운 값으로 설정 함수를 실행합니다. 컴포넌트가 DOM에서 제거된 경우에도 정리 함수를 실행합니다. +======= +* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your [component commits](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom), React will run your setup function. After every commit with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. After your component is removed from the DOM, React will run your cleanup function. + +* **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If you omit this argument, your Effect will re-run after every commit of the component. [See the difference between passing an array of dependencies, an empty array, and no dependencies at all.](#examples-dependencies) +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a + `dependencies` **선택사항** : `설정` 함수의 코드 내부에서 참조되는 모든 반응형 값들이 포함된 배열로 구성됩니다. 반응형 값에는 props와 state, 모든 변수 및 컴포넌트 body에 직접적으로 선언된 함수들이 포함됩니다. 린터가 [React 환경에 맞게 설정되어 있을 경우](/learn/editor-setup#linting), 린터는 모든 반응형 값들이 의존성에 제대로 명시되어 있는지 검증할 것입니다. 의존성 배열은 항상 일정한 수의 항목을 가지고 있어야 하며 `[dep1, dep2, dep3]`과 같이 작성되어야 합니다. React는 각각의 의존성들을 [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) 비교법을 통해 이전 값과 비교합니다. 의존성을 생략할 경우, Effect는 컴포넌트가 리렌더링될 때마다 실행됩니다. [인수에 의존성 배열을 추가했을 때, 빈 배열을 추가했을 때, 의존성을 추가하지 않았을 때의 차이를 확인해 보세요.](#examples-dependencies) @@ -112,7 +118,11 @@ function ChatRoom({ roomId }) { - 이후, <CodeStep step={1}>설정 코드</CodeStep>가 새로운 props와 state와 함께 실행됩니다. 3. 컴포넌트가 화면에서 제거된 이후에 <CodeStep step={2}>정리 코드</CodeStep>가 마지막으로 실행됩니다 *(마운트 해제 시)*. +<<<<<<< HEAD **위의 예시를 통해 순서를 설명해 보겠습니다.** +======= +**Let's illustrate this sequence for the example above.** +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 위의 `ChatRoom` 컴포넌트가 화면에 추가되면 초기 `serverUrl`과 `roomId`를 이용해 채팅방과 연결될 것입니다. 리렌더링에 의해 `serverUrl` 또는 `roomId`가 변경된다면 (예를 들어 사용자가 드롭다운 메뉴를 이용해 다른 채팅방을 선택할 경우) *Effect는 이전 채팅방과의 연결을 해제하고 다음 채팅방과 연결합니다.* `ChatRoom` 컴포넌트가 화면에서 제거된다면 Effect는 마지막 채팅방과 이뤄진 연결을 해제할 것입니다. @@ -1436,7 +1446,11 @@ function Counter() { } ``` +<<<<<<< HEAD `count`가 반응형 값이므로 반드시 의존성 배열에 추가해야 합니다. 그러나 `count`가 변경되는 것은 Effect가 정리된 후 다시 설정되는 것을 야기하므로 `count`는 계속 증가할 것입니다. 이상적이지 않은 방식입니다. +======= +Since `count` is a reactive value, it must be specified in the list of dependencies. However, that causes the Effect to cleanup and setup again every time the `count` changes. This is not ideal. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 이러한 현상을 방지하려면 [`c => c + 1` state 변경함수](/reference/react/useState#updating-state-based-on-the-previous-state)를 `setCount`에 추가하세요. diff --git a/src/content/reference/react/useEffectEvent.md b/src/content/reference/react/useEffectEvent.md index 7048b3699..c8dcae1c3 100644 --- a/src/content/reference/react/useEffectEvent.md +++ b/src/content/reference/react/useEffectEvent.md @@ -30,17 +30,29 @@ function ChatRoom({ roomId, theme }) { } ``` +<<<<<<< HEAD [아래에서 더 많은 예시를 확인하세요.](#usage) +======= +Effect Events are a part of your Effect logic, but they behave more like an event handler. They always “see” the latest values from render (like props and state) without re-synchronizing your Effect, so they're excluded from Effect dependencies. See [Separating Events from Effects](/learn/separating-events-from-effects#extracting-non-reactive-logic-out-of-effects) to learn more. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 매개변수 {/*parameters*/} - `callback`: Effect 이벤트를 위한 로직을 포함하는 함수입니다. `useEffectEvent`로 Effect 이벤트를 정의했을 때, `callback`은 실행할 때마다 항상 최신의 props와 state 값을 참조합니다. 이를 통해 오래된 클로저 문제를 피할 수 있습니다. +<<<<<<< HEAD #### 반환값 {/*returns*/} +======= +* `callback`: A function containing the logic for your Effect Event. The function can accept any number of arguments and return any value. When you call the returned Effect Event function, the `callback` always accesses the latest committed values from render at the time of the call. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a Effect 이벤트 함수를 반환합니다. `useEffect`, `useLayoutEffect` 또는 `useInsertionEffect` 내부에서 이 함수를 호출할 수 있습니다. +<<<<<<< HEAD #### 주의 사항 {/*caveats*/} +======= +`useEffectEvent` returns an Effect Event function with the same type signature as your `callback`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a - **Effect 내부에서만 호출하세요:** Effect 이벤트는 오로지 Effect 내부에서만 호출해야 합니다. 그것을 사용하는 Effect 이전에 그것을 정의하세요. 다른 컴포넌트나 훅으로 그것을 전달하지 마세요. [`eslint-plugin-react-hooks`](/reference/eslint-plugin-react-hooks) 린터(버전 6.1.1 또는 최신)는 Effect 이벤트를 잘못된 맥락에서 호출하는 것을 방지하기 위해 이 제한을 강제할 것입니다. - **의존성 지름길이 아닙니다:** Effect의 의존성 배열에 의존성을 적는 것을 피하기 위해 `useEffectEvent`를 사용하지 마세요. 이것은 버그를 숨기고 코드를 이해하는 것을 어렵게 합니다. 명시적으로 의존성을 작성하거나 필요한 경우 이전 값을 비교하기 위해 ref를 사용하세요. diff --git a/src/content/reference/react/useId.md b/src/content/reference/react/useId.md index 6f1ceaa47..6d4c46074 100644 --- a/src/content/reference/react/useId.md +++ b/src/content/reference/react/useId.md @@ -191,7 +191,11 @@ React에서 `useId`는 호출한 컴포넌트의 "부모 경로"에서 생성됩 ### 여러 개의 연관된 엘리먼트의 ID 생성하기 {/*generating-ids-for-several-related-elements*/} +<<<<<<< HEAD 여러 개의 연관된 엘리먼트에 ID를 전달하는 과정이 필요할 때 `useId`를 사용해서 공유 접두사를 생성할 수 있습니다. +======= +If you need to give IDs to multiple related elements, you can call `useId` to generate a shared prefix for them: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Sandpack> diff --git a/src/content/reference/react/useImperativeHandle.md b/src/content/reference/react/useImperativeHandle.md index a05b9b64d..d6e668c21 100644 --- a/src/content/reference/react/useImperativeHandle.md +++ b/src/content/reference/react/useImperativeHandle.md @@ -46,7 +46,11 @@ function MyInput({ ref }) { <Note> +<<<<<<< HEAD React 19 부터 [`ref`를 Prop으로 받을 수 있습니다.](/blog/2024/12/05/react-19#ref-as-a-prop) React 18 또는 그 이전 버전에서는 `ref`를 받기위해 [`forwardRef`](/reference/react/forwardRef)를 사용해야 합니다. +======= +Starting with React 19, [`ref` is available as a prop.](/blog/2024/12/05/react-19#ref-as-a-prop) In React 18 and earlier, it was necessary to get the `ref` from [`forwardRef`.](/reference/react/forwardRef) +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a </Note> diff --git a/src/content/reference/react/useInsertionEffect.md b/src/content/reference/react/useInsertionEffect.md index 985892383..23fdc3734 100644 --- a/src/content/reference/react/useInsertionEffect.md +++ b/src/content/reference/react/useInsertionEffect.md @@ -44,7 +44,13 @@ function useCSS(rule) { #### 매개변수 {/*parameters*/} +<<<<<<< HEAD * `setup`: Effects 의 로직이 포함된 함수입니다. setup 함수는 선택적으로 *cleanup* 함수를 반환할 수도 있습니다. 컴포넌트가 DOM에 추가되기 전에, layout Effects 가 실행되기 전에, React는 setup 함수를 실행합니다. `dependencies`가 변경되어 다시 렌더링할 때마다, React는 먼저 이전 값으로 cleanup 함수(제공한 경우)를 실행한 다음 새 값으로 setup 함수를 실행합니다. 컴포넌트가 DOM에서 제거되기 전에 React는 cleanup 함수를 한 번 더 실행합니다. +======= +* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your component is added to the DOM, but before any layout Effects fire, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. When your component is removed from the DOM, React will run your cleanup function. + +* **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison algorithm. If you don't specify the dependencies at all, your Effect will re-run after every re-render of the component. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a * **선택사항** `dependencies`: `setup` 코드 내에서 참조된 모든 반응형 값의 목록입니다. 반응형 값에는 props, state, 그리고 컴포넌트 본문에 직접 선언된 모든 변수와 함수가 포함됩니다. linter가 [React용으로 설정된](/learn/editor-setup#linting) 경우, 모든 반응형 값이 의존성으로 올바르게 지정되었는지 확인합니다. 의존성 목록에는 일정한 수의 항목이 있어야 하며 `[dep1, dep2, dep3]`와 같이 작성해야 합니다. React는 [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) 비교 알고리즘을 사용하여 각 의존성을 이전 값과 비교합니다. 의존성을 전혀 지정하지 않으면 컴포넌트를 다시 렌더링할 때마다 Effect가 다시 실행됩니다. diff --git a/src/content/reference/react/useOptimistic.md b/src/content/reference/react/useOptimistic.md index 6f23361be..c9ffe0fc3 100644 --- a/src/content/reference/react/useOptimistic.md +++ b/src/content/reference/react/useOptimistic.md @@ -55,7 +55,236 @@ function MyComponent({name, todos}) { `useOptimistic` Hook은 네트워크 요청과 같은 백그라운드 작업이 완료되기 전에 사용자 인터페이스를 낙관적으로 업데이트하는 방법을 제공합니다. 폼의 맥락에서, 이 기술은 앱이 더 반응적으로 느껴지도록 도와줍니다. 사용자가 폼을 제출할 때, 서버의 응답을 기다리는 대신 인터페이스는 기대하는 결과로 즉시 업데이트됩니다. +<<<<<<< HEAD 예를 들어, 사용자가 폼에 메시지를 입력하고 "전송" 버튼을 누르면, `useOptimistic` Hook은 메시지가 실제로 서버로 전송되기 전에 "전송 중..." 라벨이 있는 목록에 메시지가 즉시 나타나도록 합니다. 이 "낙관적" 접근법은 속도와 반응성의 느낌을 줍니다. 그런 다음 폼은 백그라운드에서 메시지를 실제로 전송하려고 시도합니다. 서버가 메시지를 받았음을 확인하면, "전송 중..." 라벨이 제거됩니다. +======= +function handleClick() { + startTransition(async () => { + setOptimisticLike(true); + setOptimisticSubs(a => a + 1); + await saveChanges(); + }); +} +``` + +#### Parameters {/*setoptimistic-parameters*/} + +* `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. + * 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). + +#### Returns {/*setoptimistic-returns*/} + +`set` functions do not have a return value. + +#### Caveats {/*setoptimistic-caveats*/} + +* 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. + +<DeepDive> + +#### How optimistic state works {/*how-optimistic-state-works*/} + +`useOptimistic` lets you show a temporary value while a Action is in progress: + +```js +const [value, setValue] = useState('a'); +const [optimistic, setOptimistic] = useOptimistic(value); + +startTransition(async () => { + setOptimistic('b'); + const newValue = await saveChanges('b'); + setValue(newValue); +}); +``` + +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. + +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. + +**How the update flows** + +1. **Update immediately**: When `setOptimistic('b')` is called, React immediately renders with `'b'`. + +2. **(Optional) await in Action**: If you await in the Action, React continues showing `'b'`. + +3. **Transition scheduled**: `setValue(newValue)` schedules an update to the real state. + +4. **(Optional) wait for Suspense**: If `newValue` suspends, React continues showing `'b'`. + +5. **Single render commit**: Finally, the `newValue` commits for `value` and `optimistic`. + +There's no extra render to "clear" the optimistic state. The optimistic and real state converge in the same render when the Transition completes. + +<Note> + +#### Optimistic state is temporary {/*optimistic-state-is-temporary*/} + +Optimistic state only renders while an Action is in progress, otherwise `value` is rendered. + +If `saveChanges` returned `'c'`, then both `value` and `optimistic` will be `'c'`, not `'b'`. + +</Note> + +**How the final state is determined** + +The `value` argument to `useOptimistic` determines what displays after the Action finishes. How this works depends on the pattern you use: + +- **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`. + +- **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. + +- **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. + +**What happens when the Action fails** + +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. + +</DeepDive> + +--- + +## Usage {/*usage*/} + +### Adding optimistic state to a component {/*adding-optimistic-state-to-a-component*/} + +Call `useOptimistic` at the top level of your component to declare one or more optimistic states. + +```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"]] +import { useOptimistic } from 'react'; + +function MyComponent({age, name, todos}) { + const [optimisticAge, setOptimisticAge] = useOptimistic(age); + const [optimisticName, setOptimisticName] = useOptimistic(name); + const [optimisticTodos, setOptimisticTodos] = useOptimistic(todos, reducer); + // ... +``` + +`useOptimistic` returns an array with exactly two items: + +1. The <CodeStep step={2}>optimistic state</CodeStep>, initially set to the <CodeStep step={1}>value</CodeStep> provided. +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). + * If a <CodeStep step={4}>reducer</CodeStep> is provided, it will run before returning the optimistic state. + +To use the <CodeStep step={2}>optimistic state</CodeStep>, call the `set` function inside an Action. + +Actions are functions called inside `startTransition`: + +```js {3} +function onAgeChange(e) { + startTransition(async () => { + setOptimisticAge(42); + const newAge = await postAge(42); + setAge(newAge); + }); +} +``` + +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`. + +See [How optimistic state works](#how-optimistic-state-works) for a deep dive. + +<Note> + +When using [Action props](/reference/react/useTransition#exposing-action-props-from-components), you can call the set function without `startTransition`: + +```js [[3, 2, "setOptimisticName"]] +async function submitAction() { + setOptimisticName('Taylor'); + await updateName('Taylor'); +} +``` + +This works because Action props are already called inside `startTransition`. + +For an example, see: [Using optimistic state in Action props](#using-optimistic-state-in-action-props). + +</Note> + +--- + +### Using optimistic state in Action props {/*using-optimistic-state-in-action-props*/} + +In an [Action prop](/reference/react/useTransition#exposing-action-props-from-components), you can call the optimistic setter directly without `startTransition`. + +This example sets optimistic state inside a `<form>` `submitAction` prop: + +<Sandpack> + +```js src/App.js +import { useState, startTransition } from 'react'; +import EditName from './EditName'; + +export default function App() { + const [name, setName] = useState('Alice'); + + return <EditName name={name} action={setName} />; +} +``` + +```js src/EditName.js active +import { useOptimistic, startTransition } from 'react'; +import { updateName } from './actions.js'; + +export default function EditName({ name, action }) { + const [optimisticName, setOptimisticName] = useOptimistic(name); + + async function submitAction(formData) { + const newName = formData.get('name'); + setOptimisticName(newName); + + const updatedName = await updateName(newName); + startTransition(() => { + action(updatedName); + }) + } + + return ( + <form action={submitAction}> + <p>Your name is: {optimisticName}</p> + <p> + <label>Change it: </label> + <input + type="text" + name="name" + disabled={name !== optimisticName} + /> + </p> + </form> + ); +} +``` + +```js src/actions.js hidden +export async function updateName(name) { + await new Promise((res) => setTimeout(res, 1000)); + return name; +} +``` + +</Sandpack> + +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. + +<DeepDive> + +#### Why doesn't this need `startTransition`? {/*why-doesnt-this-need-starttransition*/} + +By convention, props called inside `startTransition` are named with "Action". + +Since `submitAction` is named with "Action", you know it's already called inside `startTransition`. + +See [Exposing `action` prop from components](/reference/react/useTransition#exposing-action-props-from-components) for the Action prop pattern. + +</DeepDive> + +--- + +### Adding optimistic state to Action props {/*adding-optimistic-state-to-action-props*/} + +When creating an [Action prop](/reference/react/useTransition#exposing-action-props-from-components), you can add `useOptimistic` to show immediate feedback. + +Here's a button that shows "Submitting..." while the `action` is pending: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Sandpack> @@ -68,7 +297,7 @@ export default function App() { const [count, setCount] = useState(0); return ( <div> - <Button action={async () => { + <Button action={async () => { await submitForm(); startTransition(() => { setCount(c => c + 1); @@ -136,7 +365,7 @@ The pending state will be shown until everything in the `action` prop is finishe <Note> -You can also use [`useTransition`](/reference/react/useTransition) to get pending state via `isPending`. +You can also use [`useTransition`](/reference/react/useTransition) to get pending state via `isPending`. The difference is that `useTransition` gives you the `startTransition` function, while `useOptimistic` works with any Transition. Use whichever fits your component's needs. @@ -164,10 +393,10 @@ export default function App() { startTransition(async () => { const newValue = !optimisticIsLiked console.log('⏳ setting optimistic state: ' + newValue); - + setOptimisticIsLiked(newValue); const updatedValue = await toggleLike(newValue); - + startTransition(() => { console.log('⏳ setting real state: ' + updatedValue ); setIsLiked(updatedValue); @@ -176,11 +405,11 @@ export default function App() { } if (optimisticIsLiked !== isLiked) { - console.log('✅ rendering optimistic state: ' + optimisticIsLiked); + console.log('✅ rendering optimistic state: ' + optimisticIsLiked); } else { console.log('✅ rendering real value: ' + optimisticIsLiked); } - + return ( <button onClick={handleClick}> @@ -225,7 +454,7 @@ See [Updating state based on the current state](#updating-state-based-on-current ### Updating multiple values together {/*updating-multiple-values-together*/} -When an optimistic update affects multiple related values, use a reducer to update them together. This ensures the UI stays consistent. +When an optimistic update affects multiple related values, use a reducer to update them together. This ensures the UI stays consistent. Here's a follow button that updates both the follow state and follower count: @@ -429,7 +658,7 @@ Each optimistic item includes a `pending: true` flag so you can show loading sta ### Handling multiple `action` types {/*handling-multiple-action-types*/} -When you need to handle multiple types of optimistic updates (like adding and removing items), use a reducer pattern with `action` objects. +When you need to handle multiple types of optimistic updates (like adding and removing items), use a reducer pattern with `action` objects. This shopping cart example shows how to handle add and remove with a single reducer: @@ -703,7 +932,7 @@ export async function deleteItem(id) { </Sandpack> -Try deleting 'Deploy to production'. When the delete fails, the item automatically reappears in the list. +Try deleting 'Deploy to production'. When the delete fails, the item automatically reappears in the list. --- @@ -723,7 +952,7 @@ An optimistic state update occurred outside a Transition or Action. To fix, move </ConsoleBlockMulti> -The optimistic setter function must be called inside `startTransition`: +The optimistic setter function must be called inside `startTransition`: ```js // 🚩 Incorrect: outside a Transition @@ -772,7 +1001,7 @@ function MyComponent({ items }) { // This runs during render - not allowed! setPending(true); - + // ... } diff --git a/src/content/reference/react/useReducer.md b/src/content/reference/react/useReducer.md index 71c3b3ee9..07720999e 100644 --- a/src/content/reference/react/useReducer.md +++ b/src/content/reference/react/useReducer.md @@ -38,9 +38,15 @@ function MyComponent() { #### 매개변수 {/*parameters*/} +<<<<<<< HEAD * `reducer`: state가 어떻게 업데이트 되는지 지정하는 Reducer 함수입니다. Reducer 함수는 반드시 순수 함수여야 하며, State와 Action을 인수로 받아야 하고, 다음 State를 반환해야 합니다. State와 Action에는 모든 데이터 타입이 할당될 수 있습니다. * `initialArg`: 초기 State가 계산되는 값입니다. 모든 데이터 타입이 할당될 수 있습니다. 초기 State가 어떻게 계산되는지는 다음 `init` 인수에 따라 달라집니다. * **선택사항** `init`: 초기 State를 반환하는 초기화 함수입니다. 이 함수가 인수에 할당되지 않으면 초기 State는 `initialArg`로 설정됩니다. 할당되었다면 초기 State는 `init(initialArg)`를 호출한 결과가 할당됩니다. +======= +* `reducer`: The reducer function that specifies how the state gets updated. It must be pure, should take the state and action as arguments, and should return the next state. State and action can be of any types. +* `initialArg`: The value from which the initial state is calculated. It can be a value of any type. How the initial state is calculated from it depends on the next `init` argument. +* **optional** `init`: The initializer function that should return the initial state. If it's not specified, the initial state is set to `initialArg`. Otherwise, the initial state is set to the result of calling `init(initialArg)`. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a #### 반환값 {/*returns*/} diff --git a/src/content/reference/react/useState.md b/src/content/reference/react/useState.md index 9c32d8cd7..16c500fc5 100644 --- a/src/content/reference/react/useState.md +++ b/src/content/reference/react/useState.md @@ -529,7 +529,7 @@ export default function Form() { artwork: { title: 'Blue Nana', city: 'Hamburg', - image: 'https://i.imgur.com/Sd1AgUOm.jpg', + image: 'https://react.dev/images/docs/scientists/Sd1AgUOm.jpg', } }); diff --git a/src/content/reference/react/useSyncExternalStore.md b/src/content/reference/react/useSyncExternalStore.md index 0cb2c5acb..66a4c5620 100644 --- a/src/content/reference/react/useSyncExternalStore.md +++ b/src/content/reference/react/useSyncExternalStore.md @@ -106,7 +106,11 @@ store에 있는 데이터의 <CodeStep step={3}>snapshot</CodeStep>을 반환합 React는 이 함수를 사용해 컴포넌트를 store에 구독한 상태로 유지하고 변경 사항이 있을 때 리렌더링합니다. +<<<<<<< HEAD 예를 들어 아래 샌드박스에서 `todosStore`는 React 외부에 데이터를 저장하는 외부 store로 구현되어 있습니다. `TodosApp`컴포넌트는 `useSyncExternalStore` Hook으로 해당 외부 store에 연결합니다. +======= +For example, in the sandbox below, `todosStore` is implemented as an external store that stores data outside of React. The `TodosApp` component connects to that external store with the `useSyncExternalStore` Hook. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a <Sandpack> @@ -410,14 +414,18 @@ function ChatIndicator() { function subscribe() { // ... } - + const isOnline = useSyncExternalStore(subscribe, getSnapshot); // ... } ``` +<<<<<<< HEAD 리렌더링 사이에 다른 `subscribe` 함수를 전달하면 React가 store를 다시 구독합니다. 이로 인해 성능 문제가 발생하고 store 재구독을 피하고 싶다면 `subscribe` 함수를 외부로 이동하세요. +======= +React will resubscribe to your store if you pass a different `subscribe` function between re-renders. If this causes performance issues and you'd like to avoid resubscribing, move the `subscribe` function outside: +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a ```js {1-4} // ✅ 항상 동일한 함수이므로 React는 다시 구독할 필요가 없습니다. @@ -439,7 +447,7 @@ function ChatIndicator({ userId }) { const subscribe = useCallback(() => { // ... }, [userId]); - + const isOnline = useSyncExternalStore(subscribe, getSnapshot); // ... diff --git a/src/content/reference/rsc/server-functions.md b/src/content/reference/rsc/server-functions.md index 357464b1f..a9b9d84d3 100644 --- a/src/content/reference/rsc/server-functions.md +++ b/src/content/reference/rsc/server-functions.md @@ -22,7 +22,11 @@ title: 서버 함수 #### 서버 함수를 지원하려면 어떻게 해야 하나요? {/*how-do-i-build-support-for-server-functions*/} +<<<<<<< HEAD React 19의 서버 함수는 안정적이며 마이너<sup>Minor</sup> 버전 간에는 변경되지 않습니다. 그러나 React 서버 컴포넌트 번들러나 프레임워크에서 서버 함수를 구현하는 데 사용되는 기본 API는 유의적 버전<sup>SemVer</sup>을 따르지 않으며 React 19.x의 마이너<sup>Minor</sup> 버전 간에 변경될 수 있습니다. +======= +While Server Functions in React 19 are stable and will not break between minor versions, the underlying APIs used to implement Server Functions in a React Server Components bundler or framework do not follow semver and may break between minors in React 19.x. +>>>>>>> abe931a8cb3aee3e8b15ef7e187214789164162a 서버 함수를 번들러나 프레임워크로 지원하려면, 특정 React 버전에 고정하거나 Canary 릴리즈를 사용하는 것을 권장합니다. 향후 서버 함수를 구현하는 데 사용되는 API를 안정화하기 위해 번들러 및 프레임워크와 계속 협력할 것입니다.