과제리스트
- React Lifecycle에 대해 간단히 설명해주세요
- React18에서 업데이트 된 기능에 대해 설명해주세요
- React18에서 추가된 hook들에 대해 설명해주세요
- 요즘 관심있는 주제가 있다면 알려주세요
클라이언트와 서버간의 hydration
의 mismatch
를 피하면서 유니크 아이디
를 생성할 수 있는 새로운 훅이다. 이는 주로 고유한 'id'
가 필요한 접근성 API와 사용되는 컴포넌트에 유용할 것으로 기대된다. React18에서 새로운 스트리밍 렌더러가 HTML을 순서에 어긋나지 않게 전달해 줄 수 있다.
아이디는 기본적으로 트리 내부의 노드의 위치를 나타내는 base 32 문자열이다. 트리가 여러 children으로 분기될 때마다, 현재 레벨에서 자식 수준을 나타내는 비트를 시퀀스 왼쪽에 추가하게 된다.
이 두 메소드를 사용하면 일부 상태 업데이트를 긴급하지 않은 것(not urgent)
로 표시할 수 있다. 이 것으로 표시되지 않은 상태 업데이트는 긴급 업데이트
로 간주한다. 긴급한 상태 업데이트(ex. input text 등)가 긴급하지 않은 상태 업데이트(검색 결과 목록 렌더링)
을 중단시킬 수 있다.
function App() {
const [resource, setResource] = useState(initialResource)
const [startTransition, isPending] = useTransition({ timeoutMs: 3000 })
return (
<>
<button
disabled={isPending}
onClick={() => {
startTransition(() => {
const nextUserId = getNextId(resource.userId)
setResource(fetchProfileData(nextUserId))
})
}}
>
Next
</button>
{isPending ? 'Loading...' : null} <ProfilePage resource={resource} />
</>
)
}
startTransition
는 함수로, 리액트에 어떤 상태변화를 지연하고 싶은지 지정할 수 있다.isPending
은 진행 여부로, 트랜지션이 진행중인지 알 수 있다.timeoutMs
로 최대 3초 간 이전 화면을 유지한다.useDeferredValue
를 사용하면, 트리에서 급하지 않은 부분의 재렌더링을 지연할 수 있다. 이는 debounce
와 비슷하지만, 몇 가지 더 장점이 있다. 고정된 지연 시간이 없으므로, 리액트는 첫 번째 렌더링이 반영되는 즉시 지연 렌더링을 시도한다. 이 지연된 렌더링은 인터럽트가 가능하며, 사용자 입력을 차단하지 않는다.
import { useDeferredValue } from 'react'
const deferredValue = useDeferredValue(value, {
timeoutMs: 5000,
})
'value'의 값이 바뀌어도, 다른 렌더링이 발생하는 동안에는 최대 5000ms가 지연된다. 시간이 다되거나, 렌더링이 완료된다면 deferredValue
가 변경되면서 상태값이 변하게 될 것이다.
useSyncExternalStore
는 스토어에 대한 업데이트를 강제로 동기화하여 외부 스토어가 concurrent read
를 지원할 수 있도록하는 새로운 훅이다. 외부 데이터의 원본에 대한 subscript
를 필요로 할 때 더 이상 useEffet
를 사용하지 않고, 이는 리액트 외부 상태와 통합되는 모든 라이브러리에 권장된다.
External Store
: 외부 스토어라는 것은 우리가 subscribe하는 무언가를 의미한다. 예를 들어 리덕스 스토어, 글로벌 변수, dom 상태 등이 될 수 있다.Internal Store
: 'props', 'context', 'useState', 'useReducer' 등 리액트가 관리하는 상태를 의미한다.Tearing
: 시각적인 비일치를 의미한다. 예를 들어, 하나의 상태에 대해 UI가 여러 상태로 보여지고 있는(=각 컴포넌트 별로 업데이트 속도가 달라서 발생하는) 상태를 말한다.useInsertionEffect
는 css-in-js
라이브러리가 렌더링 도중에 스타일을 삽입할 때 성능 문제를 해결할 수 있는 새로운 훅이다. css-in-js
라이브러리를 사용하지 않는다면 사용할 필요가 없다. 이 훅은 DOM
이 한번 mutate
된 이후에 실행되지만, layout effect
가 일어나기 전에 새 레이아웃을 한 번 읽는다. 이는 React 18 이전의 문제를 해결할 수 있으며, React 18에서는 나아가 concurrent
렌더링 중에 브라우저에 리액트가 값을 반환하므로, 레이아웃을 한번 더 계산할 수 있는 기회가 생겨 매우 중요하다.
어떻게 보면 useLayoutEffect
와 비슷한데, 차이가 있다면 DOM 노드에 대한 참조에 엑세스 할 수 있다는 것이다.
(1) React DOM Client
react-dom/client
에 새로운API
가 추가되었다.
렌더링 또는 언마운트할 루트를 만드는 새로운 메소드다. ReactDOM.render
대신 사용하며, React18의 새로운 기능동작을 위해 필수로 사용해야한다.
//before
import ReactDOM from 'react-dom'
import App from 'App'
const container = document.getElementById('root')
ReactDOM.render(<App name="yceffort blog" />, container)
ReactDOM.render(<App name="yceffort post" />, container)
JAVASCRIPT
//after
import ReactDOM from 'react-dom'
import App from 'App'
const container = document.getElementById('root')
// 루트 생성
const root = ReactDOM.createRoot(container)
// 최초 렌더링
root.render(<App name="yceffort blog" />) // During an update, there is no need to pass the container again
// 업데이트 시에는, container를 다시 넘길 필요가 없다.
root.render(<App name="yceffort post" />)
서버사이드 렌더링 애플리케이션에서 hydrate
하기 위한 새로운 메소드이다. 새로운 React DOM Server API
와 함께 ReactDOM.hydrate
대신 사용하면 된다. React18의 새로운 기능동작을 위해 필수로 사용해야한다.
//before
import ReactDOM from 'react-dom'
import App from 'App'
const container = document.getElementById('root')
ReactDOM.hydrate(<App name="yceffort blog" />, container)
//after
import ReactDOM from 'react-dom'
import App from 'App'
const container = document.getElementById('root')
const root = ReactDOM.hydrateRoot(container, <App name="yceffort blog" />)
위 두 메소드 모드 'onRecoverableError'를 옵션으로 받을 수 있는데, 리액트가 렌더링이나 hydration시 에러가 발생하여 리커버리를 시도할 때 logging을 할 수 있는 목적으로 제공된다. 기본값으로 reportError나 구형 브라우저에서는 'console.error'를 쓴다.
(2) React DOM Server
'react-dom/server'에 새로운 API가 추가되었으며, 이는 서버에서 steaming Suspense를 완벽하게 지원한다.
node
환경에서 스트리밍 지원<Suspense>
와 함께 사용 가능lazy
와 함께 코드 스플리팅 가능Cloudflare
, deno
와 같이 모던 엣지 런타임 환경에서 스트리밍 지원renderToString
는 여전히 존재하지만, 사용하는 것이 권장되지는 않는다.출처: https://doqtqu.tistory.com/348#2.5.%20useInsertionEffect