DEV Community

Paramanantham Harrison
Paramanantham Harrison

Posted on • Updated on • Originally published at learnwithparam.com

Hooked with React - Learn by building book search app using react and its siblings, Part 1

Follow me on Twitter, happy to take your suggestions on topics or improvements

Lets build a simple books search page using google books API in react. While developing it, we will explore react hooks, css modules and testing in react application.

This will be a multipart series.

  1. Basic books search page using react and google books API
  2. Error Handling and loading state for the application
  3. Refactoring the code to separate components and state management
  4. Create book detail page with routing using react router
  5. Styling the page with CSS Modules
  6. Lazy loading components and pages
  7. Testing the app using jest and other kids

React app setup

Create a react app using create-react-app cli.

npx create-react-app books-search-react-hooks
Enter fullscreen mode Exit fullscreen mode

Install prettier for formatting

yarn add --dev prettier pretty-quick husky
Enter fullscreen mode Exit fullscreen mode

Lets add the precommit hooks configuration in package.json

{
  "husky": {
    "hooks": {
      "pre-commit": "pretty-quick --staged"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Creating the search UI

Lets remove the default content in App.js and add form for searching the google books API.

// App.js
import React from 'react';
import './App.css';

const App = () => {
  return (
    <section>
      <form>
        <label>
          <span>Search for books</span>
          <input
            type="search"
            placeholder="microservice, restful design, etc.,"
          />
          <button type="submit">Search</button>
        </label>
      </form>
    </section>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Search input state using useState hooks

Lets add the local state for search input using useState hooks.

// App.js
import React, { useState } from 'react';
import './App.css';

const App = () => {
  const [searchTerm, setSearchTerm] = useState('');
  const onInputChange = (e) => {
    setSearchTerm(e.target.value);
  }

  return (
    <section>
      <form onSubmit={onSubmitHandler}>
        <label>
          <span>Search for books</span>
          <input

            type="search"
            placeholder="microservice, restful design, etc.,"
            value={searchTerm}
            onChange={onInputChange}
          />
          <button type="submit">Search</button>
        </label>
      </form>
    </section>
  );
}

...
Enter fullscreen mode Exit fullscreen mode

Axios data call for books API

Let's add the form submission to call google books API. API for google books querying

https://www.googleapis.com/books/v1/volumes?q=<searchTerm>
Enter fullscreen mode Exit fullscreen mode

Lets add the logic to call the API. First add axios package for Ajax request.

yarn add axios
Enter fullscreen mode Exit fullscreen mode
// App.js
...
import axios from 'axios';
...

const App = () => {
    ...

    let API_URL = `https://www.googleapis.com/books/v1/volumes`;

    const fetchBooks = async () => {
        // Ajax call to API using Axios
        const result = await axios.get(`${API_URL}?q=${searchTerm}`);
        // Books result
        console.log(result.data);
    }

    // Submit handler
    const onSubmitHandler = (e) => {
        // Prevent browser refreshing after form submission
        e.preventDefault();
        // Call fetch books async function
        fetchBooks();
    }

    return {
        ...
        <form onSubmit={onSubmitHandler}>
        ...
    }
}
Enter fullscreen mode Exit fullscreen mode
  • first we prevent the default browser behavior of refreshing the page after form submission
  • then call the function fetchBooks which calls the google books API
  • Asynchronous books API get called using async-await and log the result to console

👏 congrats, we already fetched the API with query. Lets populate the result in a state and update our UI with search result.

Updating books search result to state

// App.js

const [books, setBooks] = useState({ items: [] });

const fetchBooks = async () => {
  const result = await axios.get(`${API_URL}?q=${searchTerm}`);
  setBooks(result.data);
};
Enter fullscreen mode Exit fullscreen mode

UI for books search result

// App.js
...

const App = () => {
  ...

  return (
    <section>
      <form onSubmit={onSubmitHandler}>
        ...
      </form>
      <ul>
        {
          books.items.map((book, index) => {
            return (
              <li key={index}>
                <div>
                  <img alt={`${book.volumeInfo.title} book`} src={`http://books.google.com/books/content?id=${book.id}&printsec=frontcover&img=1&zoom=1&source=gbs_api`} />
                  <div>
                    <h3>{book.volumeInfo.title}</h3>
                    <p>{book.volumeInfo.publishedDate}</p>
                  </div>
                </div>
                <hr />
              </li>
            );
          })
        }
      </ul>
    </section>
  );
}

...
Enter fullscreen mode Exit fullscreen mode
  • displayed the image, title and published date for the book
  • for image, we used the default image url from google books based on book ID

Lets display the books author. Each books have multiple author, it will come as an array in the result. So we will concatenate separately with this logic.

let authors = ['Param', 'Vennila', 'Afrin'];
bookAuthors(authors);
// Param, Vennila and Afrin
let authors = ['Param', 'Afrin'];
bookAuthors(authors);
// Param and Afrin
Enter fullscreen mode Exit fullscreen mode

The bookAuthors function takes the array of authors as input and concatenate the string based on the above mentioned logic.

// App.js

const bookAuthors = authors => {
  if (authors.length <= 2) {
    authors = authors.join(' and ');
  } else if (authors.length > 2) {
    let lastAuthor = ' and ' + authors.slice(-1);
    authors.pop();
    authors = authors.join(', ');
    authors += lastAuthor;
  }
  return authors;
};
Enter fullscreen mode Exit fullscreen mode

Add the authors info to the list.

// App.js

const App = () => {
  ...

  return (
    <section>
      ...
      <ul>
        {
          books.items.map((book, index) => {
            return (
              <li key={index}>
                ...
                <div>
                    <h3>{ book.volumeInfo.title }</h3>
                    <p>{ bookAuthors(book.volumeInfo.authors) }</p>
                    <p>{book.volumeInfo.publishedDate}</p>
                </div>
                ...
              </li>
            );
          })
        }
      </ul>
    </section>
  );
}

...
Enter fullscreen mode Exit fullscreen mode

Awesome, we have completed our first part of the series with simple react app using react hooks. Checkout the codesandbox example here

Hope this series help you to build your next big react app 😅. Stay tuned for the next parts of the series 🤗

Checkout the codebase for this part 1 here and the whole series codebase can be referred here.

Note: This article was originally written for my blog. I am republishing it here for the amazing DEV community.

Top comments (2)

Collapse
 
madiallo profile image
Mamadou Alpha Diallo

Thanks for sharing

Collapse
 
syed456 profile image
syed

Nice work! thanks man.