use-httpというAPIコールのライブラリが良さそうなので試してみた

公開:2020/10/10
更新:2020/10/12
5 min読了の目安(約4800字TECH技術記事

はじめに

この記事はDeveloper Roadmapsで2020年のReactロードマップの中で作者がおススメしている(前に2020年のを見た時なかったような気がする・・・?)、use-httpというHooksベースで実装されているAPIコールのパッケージを調べてみたら良さそうだったので試してみたまとめです。

公式ドキュメントはこちら
公式のGitHubのリポジトリはこちら

デモ

以下のCodeSandboxを参照ください。

何ができるの❓

RestfulAPIやGraphQLのAPIリクエストがこれ一つでできるパッケージです。
言うなればaxiosApollo Clientの機能が両方使えるようなものです。(たぶん)

パッケージインストール

$npm install use-http --save

基本的な使用法

まずは基本的な使用法で、JSONPlaceholderからusersデータをとってきてusernameを表示してみます。

useFetchの最後に渡す[]でマウント時に実行されるようになります。

UserList2.jsx
import React from "react";
import useFetch from "use-http";

const UserList = () => {
  const options = {};
  const { loading, error, data = [] } = useFetch(
    "https://jsonplaceholder.typicode.com/users", options, []
  );

  return (
    <>
      <h2>UserList</h2>
      {error && "Error!"}
      {loading && "Loading..."}
      {data.map((user) => (
        <div key={user.id}>{user.id}:{user.username}</div>
      ))}
    </>
  );
};
export default UserList;

ステートで管理したい場合

useStateなどで状態を管理したいときは、useEffectでマウントされた時にgetを使ってデータを取得しにいきます。
await get("/users");でデータ取得できます。

UserList1.jsx
import React, { useState, useEffect, useCallback } from "react";
import useFetch from "use-http";

const UserList = () => {
  const [users, setUsers] = useState([]);
  const { get, response, loading, error } = useFetch(
    "https://jsonplaceholder.typicode.com"
  );

  const initializeUsers = useCallback(async () => {
    const initialUsers = await get("/users");
    if (response.ok) setUsers(initialUsers);
  }, [get, response]);

  useEffect(() => {
    initializeUsers();
  }, [initializeUsers]); // componentDidMount

  return (
    <>
      <h2>UserList1</h2>
      {error && "Error!"}
      {loading && "Loading..."}
      {users.map((user) => (
        <div key={user.id}>
          {user.id}:{user.username}
        </div>
      ))}
    </>
  );
};
export default UserList;

ページネーション

今度はTodoをページネーションで取得したい場合です。
ページ番号をステートで管理して、欲しいページのTodoデータを取得しています。
onNewDataのところで、現在のTodoデータに新しいTodoデータを連結しています。
普通に次のページの分だけ表示する場合はonNewData: (currTodos, newTodos) => newTodos,のようにそのまま新しい取得データにしてやればいけます。

TodoList.jsx
import React, { useState } from "react";
import useFetch from "use-http";

const TodoList = () => {
  const [page, setPage] = useState(1);
  const perPage = 10;
  const { loading, data: todos } = useFetch(
    `/todos?_start=${(page - 1) * perPage}&_limit=${perPage}`,
    {
      onNewData: (currTodos, newTodos) => [...currTodos, ...newTodos],
      data: []
    },
    [page]
  );
  return (
    <>
      <h2>TodoList</h2>
      {todos.map((todo, index) => (
        <div key={index}>
          {todo.id}:{todo.title}
        </div>
      ))}
      {loading && "Loading..."}
      {!loading && (
        <button onClick={() => setPage(page + 1)}>Load More Todos</button>
      )}
    </>
  );
};
export default TodoList;
App.jsx
import React from "react";
import { Provider } from "use-http";
import TodoList from "./TodoList";

export default function App() {
  const options = {
    headers: {
      Accept: `application/json`
    }
  };

  return (
    <div className="App">
      <Provider options={options} url="https://jsonplaceholder.typicode.com">
        <TodoList />
      </Provider>
    </div>
  );
}

GraphQL Query

GrapuQLのQueryもuseFetchを使ってリクエストできます。
以下はドキュメント原文ままです。

一旦queryを定義しておいて、useFetchを使用して、GraphQLのQueryでリクエストできます。

const QUERY = `
  query Todos($userID string!) {
    todos(userID: $userID) {
      id
      title
    }
  }
`
function App() {
  const request = useFetch('http://example.com')
  const getTodosForUser = id => request.query(QUERY, { userID: id })

  return (
    <>
      <button onClick={() => getTodosForUser('theUsersID')}>Get User's Todos</button>
      {request.loading ? 'Loading...' : <pre>{request.data}</pre>}
    </>
  )
}

GraphQL Mutation

GrapuQLのMutationもuseFetchを使ってリクエストできます。
以下はドキュメント原文ままです。

一旦Mutationを定義しておいて、useFetchを使用して、GraphQLのMutationでリクエストできます。

const MUTATION = `
  mutation CreateTodo($todoTitle string) {
    todo(title: $todoTitle) {
      id
      title
    }
  }
`
function App() {
  const [todoTitle, setTodoTitle] = useState('')
  const request = useFetch('http://example.com')
  const createtodo = () => request.mutate(MUTATION, { todoTitle })

  return (
    <>
      <input onChange={e => setTodoTitle(e.target.value)} />
      <button onClick={createTodo}>Create Todo</button>
      {request.loading ? 'Loading...' : <pre>{request.data}</pre>}
    </>
  )
}

まとめ

他にも様々な機能があるので、公式ドキュメントを参照してみてください。
個人的にはApollo Clientを勉強中だったので、こちらもしっかり勉強する必要があると思いました。