🚶‍♂️

ReactとGoogle Books APIで本検索アプリを作る

2022/07/25に公開

今回はReactプロジェクトの中で、Google Books APIを使用し簡易的な本検索アプリを制作します。検索窓を設置し書籍のタイトルを入力して送信すると、情報を取得、結果をレンダリングします。
以下が完成形になります。

キャプチャの場合スクロールするとブコウスキーの関連書籍が続きます。

使用する主な技術

  • React(create-react-appによる開発)
  • ReactHooks(useState、useEffect、カスタムHook)
  • Chakra UI(スタイルをあてる)

create-react-appでReactプロジェクトを作る

まずはReactの開発環境を構築していきましょう。ターミナルで以下のコマンドを打つだけです。(Node.jsのインストールが済んでることを想定しています。)
books-appの部分は自分の好きなプロジェクト名に変えていただいて問題ありません。

npx create-react-app books-app

Chakra UIをインストールする

以下のサイトに沿ってChakra UIをnpm installして設定していきます。
https://chakra-ui.com/

BooksSearchコンポーネントを作る

検索窓を設置するコンポーネントとしてBooksSearch.jsxを作成します。

import { Input } from '@chakra-ui/react';
import { Heading } from '@chakra-ui/react';

const BooksSearch = () => {

  return (
    <div>
      <Heading as='h1' size='xl' mb='5'>Book Title</Heading>
      <form className="text-xl">
        <Input />
      </form>
    </div>
  );

}
export default BooksSearch;

Chakra UIによって定義されたコンポーネントを使ってスタイルをあてています。

BooksResultコンポーネントを作る

検索結果をレンダリングするためのコンポーネントを作成します。

import { memo } from "react";
import { Text } from '@chakra-ui/react';
import { Heading } from '@chakra-ui/react';

const BooksResult = memo((props) => {

  return (
    <div>
      <div className="mb-16">
      </div>
    </div>
  )
})
export default BooksResult;

現状はほぼ空のコンポーネントになります。このコンポーネントはBooksSearchを親に持つ想定なので不要なレンダリングを避けるためにメモ化しています。

カスタムHookのuseSearch.jsを作る

hooksフォルダを作成、その中にuseSearch.jsを書いていきます。

import { useState } from 'react';

const useSearch = () => {

  const [items, setItems] = useState([]);
  const [value, setValue] = useState("");

  const handleNewBooks = (event) => {
    setValue(event.target.value);
  };

  const searchBooks = async (event) => {
    event.preventDefault();
    if (value === '') return;
    const endpoint = 'https://www.googleapis.com/books/v1';
    const res = await fetch(`${endpoint}/volumes?q=${value}`);
    const data = await res.json();
    const dataFormat = data.items.map(item => {
    const Info = item.volumeInfo;
    return {
      title: Info.title,
      description: Info.description,
      link: Info.infoLink,
      image: Info.imageLinks ? Info.imageLinks.smallThumbnail : '',
      };
    });
    setItems(dataFormat);
  }

  return {handleNewBooks,searchBooks,items,value}

}
export default useSearch;

useStateでAPIからの返却値を格納するitemsと、検索窓にタイプする値を監視するvalueを定義します。
APIへのアクセスはfeachで行い、返ってきた値をフォーマットしてからsetItemsで更新しています。
そして全ての関数とstateをreturnしておきます。

BooksSearchコンポーネント追記

import useSearch from "../hooks/useSearch";
import BooksResult from "../components/BooksResult";
import { Input } from '@chakra-ui/react';
import { Heading } from '@chakra-ui/react';

const BooksSearch = () => {

  const { handleNewBooks, searchBooks, value, items } = useSearch();

  return (
    <div>
      <Heading as='h1' size='xl' mb='5'>Book Title</Heading>
      <form onSubmit={searchBooks} className="text-xl">
        <Input onChange={handleNewBooks} value={value} />
      </form>
      <BooksResult items={items} />
    </div>
  );

}
export default BooksSearch;

BooksResultコンポーネントの読み込みをして、propsにカスタムHookから持ってきたitemsを渡します。formにはsearchBooksをトリガーとして、検索窓に書籍のタイトルを記入後(handleNewBooks)、enterでAPIにアクセスします。

BooksResultコンポーネント追記

import { memo } from "react";
import { Text } from '@chakra-ui/react';
import { Heading } from '@chakra-ui/react';

const BooksResult = memo((props) => {

  const { items } = props;

  return (
    <div>
      <div className="mb-16">
        {items.map((item, index) => {
          return (<div className="text-lg m-8"
            key={index}>
            <a href={item.link} target='_blank' >
              <img src={item.image} />
              <div className='p16'>
                <Heading as='h2' size='xl' mt='10'>{item.title}</Heading>
                <Text align='justify' fontSize='xl' mt='10'>{item.description}</Text>
              </div>
            </a>
          </div>)
        })}
      </div>
    </div>
  )
})
export default BooksResult;

フォーマットされたitemsをpropsで受け取り、それを元にmapでアクセスしてレンダリングしています。

App.jsを編集

最後にApp.jsにBookSearchコンポーネントを読み込みます。

import BooksSearch from './components/BooksSearch';
import './App.css';
import { ChakraProvider } from '@chakra-ui/react';
import { Container } from '@chakra-ui/react';

function App() {
  return (
    <ChakraProvider>
      <div className="App">
        <Container maxW='container.sm'>
          <BooksSearch />
        </Container>
      </div>
    </ChakraProvider>
  );
}

export default App;

これで完成となります。

終わり

今回はReactとGoogle Books APIで簡易的な本検索アプリを作ってみました。Chakra UIはとても簡単にスタイルが整えられていいですね。引き続きReact学習していきます。

参考文献

https://zenn.dev/phi/articles/javascript-tool-google-books-api

Discussion