2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ReactコンポーネントでWebAPIからデータを取得し画面に表示するまで[改]

Posted at

はじめに

昔こんな記事を書きました。

しかし、外部リソースからデータを fetch する目的であれば、必ずしも useEffect を使う必要はなく、むしろ別の方法のほうがいいとも言われています。

ということなので、こちらの記事を参考にしつつ、useEffect を使ってデータフェッチしている処理から useEffect を取り除いていきます。

useEffectを使用する場合

type Todo = {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
};

const fetchPosts = async (): Promise<Post[]> => {
  const res = await fetch(
    "https://jsonplaceholder.typicode.com/posts/?_limit=10"
  );
  return res.json();
};

const PostList: React.FC = () => {
  const [posts, setPosts] = useState<Post[]>([]);

  useEffect(() => {
    (async function () {
      const data = await fetchPosts();

      setPosts(data);
    })();
  }, []);

  return (
    <div>
      <h2>todos</h2>
      <ul>
        {todos?.map((todo) => (
          <li key={todo.id}>
            <p>title: {todo.title}</p>
          </li>
        ))}
      </ul>
    </div>
  );
};

コンポーネントがレンダリングされる際に一度だけ useEffect 内の処理が実行され、WebAPI からデータをフェッチします。

useEffectを使用しない場合

useSyncExternalStore を使用します。

import { useCallback, useRef, useSyncExternalStore } from "react";
import axios from "axios";

type Todo = {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
};

export const Todos: React.FC = () => {
  const data$ = useRef<Todo[]>();

  const subscribe = useCallback((onStoreChange: () => void): (() => void) => {
    const controller = new AbortController();

    axios
      .get<Todo[]>("/https://jsonplaceholder.typicode.com/posts/?_limit=10", { signal: controller.signal })
      .then((res) => res.data)
      .then((data) => {
        data$.current = data;

        onStoreChange();
      });

    return () => controller.abort();
  }, []);

  const todos = useSyncExternalStore(subscribe, () => data$.current);

  return (
    <div>
      <h2>todos</h2>
      <ul>
        {todos?.map((todo) => (
          <li key={todo.id}>
            <p>title: {todo.title}</p>
          </li>
        ))}
      </ul>
    </div>
  );
};
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?