--- title: 'Summary of React Version 19' author: 'Hun Im' date: 2024-10-22T10:40:35+09:00 category: ['POSTS'] tags: ['Javascript', 'React'] og_image: '/images/gamer.png' keywords: ['Javascript', 'React'] --- ## Major New Features 1. Actions - Enhanced support for asynchronous functions: By using `useTransition`, you can automatically manage pending states, error handling, and optimistic updates in asynchronous functions. ```jsx const [isPending, startTransition] = useTransition() const handleSubmit = () => { startTransition(async () => { const error = await updateName(name) if (error) { setError(error) return } redirect('/path') }) } ``` 2. New Hook: `useActionState` - Easily handle common cases of Actions: Manage the results of asynchronous actions, pending states, errors, and more. ```jsx const [error, submitAction, isPending] = useActionState( async (prevState, formData) => { const error = await updateName(formData.get('name')) if (error) return error redirect('/path') return null }, null ) ``` 3. React DOM: <form> Actions and `useFormStatus` - Pass functions as `action` and `formAction` props: Automatically manage form submissions and reset the form after submission. - Added `useFormStatus` hook: Supports access to form state in design systems. ```jsx function DesignButton() { const { pending } = useFormStatus() return <button type="submit" disabled={pending} /> } ``` 4. New Hook: `useOptimistic` - Manage optimistic updates: Provide immediate feedback to users while asynchronous requests are in progress. ```jsx const [optimisticName, setOptimisticName] = useOptimistic(currentName) const submitAction = async (formData) => { const newName = formData.get('name') setOptimisticName(newName) const updatedName = await updateName(newName) onUpdateName(updatedName) } ``` 5. New API: `use` - Support reading resources during rendering: Use `use` to read promises or contexts and suspend components if necessary. ```jsx function Comments({ commentsPromise }) { const comments = use(commentsPromise) return comments.map((comment) => <p key={comment.id}>{comment}</p>) } ``` 6. React Server Components - Support for server components: Pre-render components on the server to reduce client bundle sizes and improve performance. - Server Actions: Call asynchronous functions that execute on the server from client components. ## Improvements 1. Passing ref as a Prop - No need for forwardRef: You can directly receive and use ref as a prop in functional components. ```jsx function MyInput({ placeholder, ref }) { return <input placeholder={placeholder} ref={ref} /> } ``` 2. Improved Debugging for Hydration Errors - Providing diffs: More clear messages and debugging information for errors occurring during hydration. 3. Using <Context> as a Provider - More concise context usage: You can provide context values using <Context> instead of <Context.Provider>. ```jsx const ThemeContext = createContext('') function App({ children }) { return <ThemeContext value="dark">{children}</ThemeContext> } ``` 4. Support for Cleanup Functions in ref - Return cleanup functions: You can return a cleanup function from a ref callback to execute when a component unmounts. ```jsx <input ref={(ref) => { // Executes when ref is created return () => { // Executes during ref cleanup } }} /> ``` 5. Initial Value Support in `useDeferredValue` - Setting an initial value: Add an `initialValue` option to `useDeferredValue` to specify the value used during initial rendering. ```jsx const value = useDeferredValue(deferredValue, '') ``` 6. Support for Document Metadata - Natural use of `<title>, <meta>, <link>` tags: Define document metadata directly within components, and React automatically hoists them to `<head>`. ```jsx function BlogPost({ post }) { return ( <article> <h1>{post.title}</h1> <title>{post.title}</title> <meta name="author" content="Author Name" /> </article> ) } ``` 7. Improved Stylesheet Support - Managing stylesheet precedence: Control the insertion order of stylesheets using the precedence attribute on `<link>` tags. ```jsx <link rel="stylesheet" href="style.css" precedence="high" /> ``` 8. Support for Asynchronous Scripts - Managing load order and deduplication: Declare asynchronous scripts within components, and React manages load order and deduplication. ```jsx function MyComponent() { return ( <div> <script async src="script.js" /> Content </div> ) } ``` 9. Support for Resource Preloading - Performance optimization: Provide APIs like `preload`, `prefetchDNS`, `preconnect` to optimize browser resource loading. ```jsx import { prefetchDNS, preconnect, preload, preinit } from 'react-dom' function MyComponent() { preinit('https://example.com/script.js', { as: 'script' }) preload('https://example.com/font.woff', { as: 'font' }) } ``` 10. Improved Compatibility with Third-Party Scripts and Extensions - Enhanced hydration: Prevent hydration errors caused by unexpected tags or elements, minimizing conflicts with third-party scripts or browser extensions. 11. Improved Error Reporting - Removing duplication and providing detailed information: Eliminate duplicate error messages and add new root options like `onCaughtError`, `onUncaughtError` for flexible error handling. 12. Support for Custom Elements - Improved attribute and property management: Enhanced handling of attributes and properties for custom elements, ensuring consistent behavior in client and SSR environments.
ย
--- title: '๋ฆฌ์กํธ 19๋ฒ์ ์ ๋ฆฌ' author: '์ํ' date: 2024-10-22T10:40:35+09:00 category: ['POSTS'] tags: ['Javascript', 'React'] og_image: '/images/gamer.png' keywords: ['Javascript', 'React'] --- ## ์ฃผ์ ์๋ก์ด ๊ธฐ๋ฅ 1. Actions - ๋น๋๊ธฐ ํจ์ ์ง์ ๊ฐํ: `useTransition`์ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ํจ์์์ ์๋์ผ๋ก pending ์ํ, ์ค๋ฅ ์ฒ๋ฆฌ, ๋๊ด์ ์ ๋ฐ์ดํธ๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ```jsx const [isPending, startTransition] = useTransition() const handleSubmit = () => { startTransition(async () => { const error = await updateName(name) if (error) { setError(error) return } redirect('/path') }) } ``` 2. ์๋ก์ด ํ : `useActionState` - Actions์ ๊ณตํต ์ฌ๋ก๋ฅผ ์ฝ๊ฒ ์ฒ๋ฆฌ: ๋น๋๊ธฐ ์ก์ ์ ๊ฒฐ๊ณผ, pending ์ํ, ์ค๋ฅ ๋ฑ์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ```jsx const [error, submitAction, isPending] = useActionState( async (prevState, formData) => { const error = await updateName(formData.get('name')) if (error) return error redirect('/path') return null }, null ) ``` 3. React DOM: <form> Actions ๋ฐ `useFormStatus` - ํจ์๋ฅผ action ๋ฐ formAction prop์ผ๋ก ์ ๋ฌ: ํผ ์ ์ถ์ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ฉฐ, ์ ์ถ ํ ํผ์ ์๋์ผ๋ก ์ฌ์ค์ ํฉ๋๋ค. - useFormStatus ํ ์ถ๊ฐ: ๋์์ธ ์์คํ ์์ ํผ์ ์ํ์ ์ ๊ทผํ ์ ์๋๋ก ์ง์ํฉ๋๋ค. ```jsx function DesignButton() { const { pending } = useFormStatus() return <button type="submit" disabled={pending} /> } ``` 4. ์๋ก์ด ํ : `useOptimistic` - ๋๊ด์ ์ ๋ฐ์ดํธ ๊ด๋ฆฌ: ๋น๋๊ธฐ ์์ฒญ์ด ์งํ๋๋ ๋์ ์ฌ์ฉ์์๊ฒ ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ```jsx const [optimisticName, setOptimisticName] = useOptimistic(currentName) const submitAction = async (formData) => { const newName = formData.get('name') setOptimisticName(newName) const updatedName = await updateName(newName) onUpdateName(updatedName) } ``` 5. ์๋ก์ด API: `use` - ๋ฆฌ์์ค๋ฅผ ๋ ๋๋ง ์ค์ ์ฝ๊ธฐ ์ง์: use๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก๋ฏธ์ค๋ ์ปจํ ์คํธ๋ฅผ ์ฝ๊ณ , ํ์ํ ๊ฒฝ์ฐ ์ปดํฌ๋ํธ๋ฅผ ์ผ์ ์ค๋จ(Suspend)ํ ์ ์์ต๋๋ค. ```jsx function Comments({ commentsPromise }) { const comments = use(commentsPromise) return comments.map((comment) => <p key={comment.id}>{comment}</p>) } ``` 6. React ์๋ฒ ์ปดํฌ๋ํธ - ์๋ฒ ์ปดํฌ๋ํธ ์ง์: ์๋ฒ์์ ์ฌ์ ๋ ๋๋งํ์ฌ ํด๋ผ์ด์ธํธ ๋ฒ๋ค ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ , ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. - ์๋ฒ ์ก์ : ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์ ์๋ฒ์์ ์คํ๋๋ ๋น๋๊ธฐ ํจ์๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค. ## ๊ฐ์ ์ฌํญ 1. ref๋ฅผ Prop์ผ๋ก ์ ๋ฌ - forwardRef ๋ถํ์: ํจ์ํ ์ปดํฌ๋ํธ์์ ref๋ฅผ ์ง์ Prop์ผ๋ก ๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ```jsx function MyInput({ placeholder, ref }) { return <input placeholder={placeholder} ref={ref} /> } ``` 2. Hydration ์ค๋ฅ์ ๋ํ ๊ฐ์ ๋ ๋๋ฒ๊น - ์ฐจ์ด์ (diff) ์ ๊ณต: Hydration ์ ๋ฐ์ํ๋ ์ค๋ฅ์ ๋ํด ๋ ๋ช ํํ ๋ฉ์์ง์ ๋๋ฒ๊น ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค. 3. <Context>๋ฅผ ํ๋ก๋ฐ์ด๋๋ก ์ฌ์ฉ - ๋ ๊ฐ๊ฒฐํ ์ปจํ ์คํธ ์ฌ์ฉ๋ฒ: <Context.Provider> ๋์ <Context>๋ฅผ ์ฌ์ฉํ์ฌ ์ปจํ ์คํธ ๊ฐ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ```jsx const ThemeContext = createContext('') function App({ children }) { return <ThemeContext value="dark">{children}</ThemeContext> } ``` 4. ref์ ์ ๋ฆฌ ํจ์ ์ง์ - ํด๋ฆฐ์ ํจ์ ๋ฐํ: ref ์ฝ๋ฐฑ์์ ์ ๋ฆฌ(cleanup) ํจ์๋ฅผ ๋ฐํํ์ฌ ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋ ์คํ๋๋๋ก ํ ์ ์์ต๋๋ค. ```jsx <input ref={(ref) => { // ref ์์ฑ ์ ์คํ return () => { // ref ์ ๋ฆฌ ์ ์คํ } }} /> ``` 5. useDeferredValue์ ์ด๊ธฐ ๊ฐ ์ง์ - ์ด๊ธฐ ๊ฐ ์ค์ : useDeferredValue์ initialValue ์ต์ ์ ์ถ๊ฐํ์ฌ ์ด๊ธฐ ๋ ๋๋ง ์ ์ฌ์ฉํ ๊ฐ์ ์ง์ ํ ์ ์์ต๋๋ค. ```jsx const value = useDeferredValue(deferredValue, '') ``` 6. ๋ฌธ์ ๋ฉํ๋ฐ์ดํฐ ์ง์ - `<title>, <meta>, <link>`ํ๊ทธ์ ์์ฐ์ค๋ฌ์ด ์ฌ์ฉ: ์ปดํฌ๋ํธ ๋ด์์ ๋ฌธ์์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ง์ ์ ์ํ๊ณ , React๊ฐ ์ด๋ฅผ `<head>`๋ก ์๋ ํธ์ด์คํ ํฉ๋๋ค. ```jsx function BlogPost({ post }) { return ( <article> <h1>{post.title}</h1> <title>{post.title}</title> <meta name="author" content="Author Name" /> </article> ) } ``` 7. ์คํ์ผ์ํธ ์ง์ ๊ฐ์ - ์คํ์ผ์ํธ์ ์ฐ์ ์์ ๊ด๋ฆฌ: `<link>` ํ๊ทธ์ precedence ์์ฑ์ ์ฌ์ฉํ์ฌ ์คํ์ผ์ํธ์ ์ฝ์ ์์๋ฅผ ์ ์ดํ ์ ์์ต๋๋ค. ```jsx <link rel="stylesheet" href="style.css" precedence="high" /> ``` 8. ๋น๋๊ธฐ ์คํฌ๋ฆฝํธ ์ง์ - ์ค๋ณต ์ ๊ฑฐ ๋ฐ ๋ก๋ ์์ ๊ด๋ฆฌ: ๋น๋๊ธฐ ์คํฌ๋ฆฝํธ๋ฅผ ์ปดํฌ๋ํธ ๋ด์์ ์ ์ธํ๊ณ , React๊ฐ ๋ก๋ ์์์ ์ค๋ณต์ ๊ด๋ฆฌํฉ๋๋ค. ```jsx function MyComponent() { return ( <div> <script async src="script.js" /> Content </div> ) } ``` 9. ๋ฆฌ์์ค ํ๋ฆฌ๋ก๋ฉ ์ง์ - ์ฑ๋ฅ ์ต์ ํ: preload, prefetchDNS, preconnect ๋ฑ์ API๋ฅผ ์ ๊ณตํ์ฌ ๋ธ๋ผ์ฐ์ ๋ฆฌ์์ค ๋ก๋ฉ์ ์ต์ ํํฉ๋๋ค. ```jsx import { prefetchDNS, preconnect, preload, preinit } from 'react-dom' function MyComponent() { preinit('https://example.com/script.js', { as: 'script' }) preload('https://example.com/font.woff', { as: 'font' }) } ``` 10. ์๋ํํฐ ์คํฌ๋ฆฝํธ ๋ฐ ํ์ฅ ํ๋ก๊ทธ๋จ๊ณผ์ ํธํ์ฑ ํฅ์ - Hydration ๊ฐ์ : ์๊ธฐ์น ์์ ํ๊ทธ๋ ์์๋ก ์ธํ Hydration ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๊ณ , ์๋ํํฐ ์คํฌ๋ฆฝํธ๋ ๋ธ๋ผ์ฐ์ ํ์ฅ ํ๋ก๊ทธ๋จ๊ณผ์ ์ถฉ๋์ ์ต์ํํฉ๋๋ค. 11. ์ค๋ฅ ๋ณด๊ณ ๊ฐ์ - ์ค๋ณต ์ ๊ฑฐ ๋ฐ ์์ธ ์ ๋ณด ์ ๊ณต: ์ค๋ฅ ๋ฉ์์ง์ ์ค๋ณต์ ์ ๊ฑฐํ๊ณ , `onCaughtError`, `onUncaughtError` ๋ฑ์ ์๋ก์ด ๋ฃจํธ ์ต์ ์ ์ถ๊ฐํ์ฌ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ ์ฐํ๊ฒ ํฉ๋๋ค. 12. ์ปค์คํ ์๋ฆฌ๋จผํธ ์ง์ - ์์ฑ ๋ฐ ํ๋กํผํฐ ๊ด๋ฆฌ ๊ฐ์ : ์ปค์คํ ์๋ฆฌ๋จผํธ์ ๋ํ ์์ฑ๊ณผ ํ๋กํผํฐ ์ฒ๋ฆฌ๊ฐ ๊ฐ์ ๋์ด, ํด๋ผ์ด์ธํธ ๋ฐ SSR ํ๊ฒฝ์์ ์ผ๊ด์ฑ ์๊ฒ ๋์ํฉ๋๋ค.