0w0

이제와서 알아보는 React v18

React Conf 영상을 보며 사내 10분 공부회에서 공유한 자료입니다.

React Conf

(개인적) React v18의 핵심

글에서는 React18보다 suspense 이야기가 주가 되겠네요

Suspense에 의해 무엇이 변하는가

fetch on render 코드

ref: https://ko.reactjs.org/docs/concurrent-mode-suspense.html#approach-1-fetch-on-render-not-using-suspense

function ProfilePage() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchUser().then((u) => setUser(u));
  }, []);

  if (user === null) {
    return <p>Loading profile...</p>;
  }
  return (
    <>
      <h1>{user.name}</h1>
      <ProfileTimeline />
    </>
  );
}

function ProfileTimeline() {
  const [posts, setPosts] = useState(null);

  useEffect(() => {
    fetchPosts().then((p) => setPosts(p));
  }, []);

  if (posts === null) {
    return <h2>Loading posts...</h2>;
  }
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.text}</li>
      ))}
    </ul>
  );
}

suspense

Server rendering With suspense

SSR


CSR

=> SSR, CSR 둘 다, 읽는데 애플리케이션 전체를 멈출 필요가 있었다

hydration

React18에서는 분할해서 HTML를 보이며, 각각을 부분적으로 hydrate할 수 있다🎉

=> 이를 실현하는 것이 Streaming HTML

streaming HTML image

Streaming HTML

Streaming HTML example

비동기적으로 hydrate하고 있어서, HTML를 빨리 보일 수 있고, 데이터를 얻기가 완료될 때부터 인터렉티브하게 할 수 있다

구현

<Suspense fallback={<Spinner />}>
  <Comments />
</Suspense>

이 코드는 이렇게 된다.

// This is not a Promise. It's a special object from our Suspense integration.
const resource = fetchProfileData();

function ProfilePage() {
  return (
    <Suspense fallback={<h1>Loading profile...</h1>}>
      <ProfileDetails />
      <Suspense fallback={<h1>Loading posts...</h1>}>
        <ProfileTimeline />
      </Suspense>
    </Suspense>
  );
}

function ProfileDetails() {
  // Try to read user info, although it might not have loaded yet
  const user = resource.user.read();
  return <h1>{user.name}</h1>;
}

function ProfileTimeline() {
  // Try to read posts, although they might not have loaded yet
  const posts = resource.posts.read();
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.text}</li>
      ))}
    </ul>
  );
}

역주: 공식으로 react18이 출시되었으니 문서 참조 https://reactjs.org/docs/react-api.html#reactsuspense

// This component is loaded dynamically
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    // Displays <Spinner> until OtherComponent loads
    <React.Suspense fallback={<Spinner />}>
      <div>
        <OtherComponent />
      </div>
    </React.Suspense>
  );
}

hydration이 완료된 곳부터 인터렉팅 가능

done hydration and interacting parts

Selective Hydration

click and hydration

automatic batching

useDeferredValue

const defferedValue = useDeferredValue({
  /*무거운처리*/
});

React Server Components

SSR와 차이점

정리

참고자료

https://github.com/reactjs/rfcs/pull/188