non117's diary

料理と哲学をします

React Concurrent Mode雑感

 Concurrent Modeのドキュメントを読みました。useEffect によるFetch-on-render から、Suspense によるRender-as-You-Fetch への変化が本質にみえます。

before

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() {
 // 省略
}

after

// 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>
  );
}

*1

 いいですね。if (user === null) { が消えています。読みやすいですね。でも、ひとつ疑問があります。resource.user.read() これはなんなのか。
 Facebookの答えはRelayです。Relay is a JavaScript framework for building data-driven React applications powered by GraphQL だそうです。useLazyLoadQuery が重要なhookになります*2。とはいえ、Relayそのものを使えという話ではありません。サーバーとクライアントのお喋りをいい感じにやる君が必要なだけです。後ろにservice workerがいるのかもしれませんし、in-memoryでキャッシュしているかもしれません。もっと素朴に作るなら、Lazy Loadとキャッシュ機構抜きで、データのfetchと加工を隠蔽してくれれば大丈夫です。
 Suspense を使ってとりあえずrenderされるUIを作るには、賢めのデータとる君が必要になりそうです。自作をしても良いですし、Relayのようなフレームワークに乗っかってもよいです。最悪なのは、resource.user.read() の行でfetch し始めることです。UI定義の中でエラーハンドリング、データの変形をやり始めると、Presentation Domain Separation*3から遠ざかりますし、何より読みにくくなります。
 元はといえば、useEffectの時からそうでした*4。何でも非同期処理を書けるのでuseEffectは割れ窓にできます。componentDidMountの時代から可能だったと言えばそう。Facebookにいる人々のレベルが高いからかもしれませんし、React is a JavaScript library for building user interfaces の責務に忠実だから危険なほどの自由さがあるのかもしれません。Reactの各種APIはとても便利にできています。プログラマは柔軟にUIを構築できます。ですが、Reactでメンテナンスしやすいコードを書くには(そこそこ深く)考え続けなければなりません。自由とはそういうものですし、制約の少ないフレームワークにするのがReactのやり方なのでしょう。私は自由と考え事が多いものは好みですが、チームで開発すると苦労は増えます。

f:id:non_117:20191103204013j:plain
積み木をするめんだこ
*5
 Reactは着実に進化しており、ますます柔軟にUIを作れるようになっています。Presentation Domain SeparationとReactの自由さ、開発者のスケーラビリティすべて満たすのはたいへんそうだなと思ったのでした。