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