First Chingu Solo Project SoloBookFinder

Chris V Sanchez
7 min readFeb 3, 2021

I will break down my first Chingu Solo Project submission, which was accepted for Chingu Voyage 27. The application was built with JavaScript using React library, CSS for styling and deployed with Heroku. The purpose of the application was to utilize Google Books API to search books and click on a more details button to access more information, make sure the styling is responsive, include error handling, and only search for books upon clicking submit button. Finally, deploy. My focus will be unpacking the React portion and Heroku deployment, if you are interested in checking out the CSS, you can click on the Github link below.

SoloBookFinder satisfied its Chingu solo project requirements for tier 2. This app example is a great start to create something like a GoodReads variation by adding more features and a backend.

For those who want to jump the gun and check out Github or SoloBookFinder deployed.

  1. Wireframe/Component Hierarchy
  2. Create React App/Logic
  3. Deploy on Heroku

BUILDING A WIREFRAME

I built my wireframe using LucidChart. The app was required to show information from the Google Books API. Specifically, the user should see the title, book cover, author, publisher, and a button that links to more information about the particular book.

COMPONENT HIERARCHY

CREATE REACT APP / LOGIC

Open the terminal or command prompt of your preference and cd into the main directory to create your app. Then enter npx create-react-app ${APPNAME} in the command line. Assuming you have already installed npm and node.

Once I open my application in VS code, I create a component folder in the src folder. Then I create the two child components of my App component as demonstrated in the component hierarchy.

Throughout this project, I am only using function components because that is the future of React (all updates since React hooks have focused on enhancing functional components in React).

Let’s get started with App.js.

The App.js/Parent Component

The image on the left shows my imports. First, I am importing my App.css for styling. Second, I’ll import useState from React. After all, I will manage the state in the parent component because I’ll use it to update the API call to show BooksCards. Then I’ll import my two components from the component hierarchy. The bookIcon import is for the books that have no book cover to be replaced with an SVG, and the LoadingBooks gif is used for the loading screen when searching until the API call returns a response. If it doesn't make sense right now, it's okay. I’ll show you how they get implemented later on.

I declare the App function and begin to use React Hooks useState to manage state and assign my API_ENDPOINT(the link is found in Google Books API docs) to make fetch requests based on searchTerm. I create a state to manage the books from fetch with the value of an empty array, searchTerm with the value of an empty string, isLoading is used to conditionally render the loading gif until the fetch response is returned. Lastly, I manage the isError also conditionally to render error messages. I assigned the booleans to the state that will influence conditional rendering.

HandleSearchInput

Right below the imports. I created a handleSearchInput function that will update the state onChange whenever the user types anything in the input field. This function will be passed as props to the search component and the parent will be updated right away. It uses useState to update the searchTerm.

HandleSubmit

The handleSubmit function will be passed as props to the search component. This function will be triggered once the search button in the Search.js component is clicked on, with an onClick event handler.

e.preventDefault() prevents the default behavior for the button and continues to run the rest of the code. I set the two boolean state values for setIsLoading(true) and setIsError(false) because they will be used to render data later on conditionally. Once isLoading is set to true, it will conditionally start to render the loading gif imported earlier in App.js. It will be removed by setting setIsLoading to false once I get a response from the API call.

Next, The fetch will make an API call by interpolating the search term with the API_ENDPOINT. You check out the Google Books documentation for more ways to structure the API string to obtain different information. If the response is successful, it will setBooks, followed by using the successful response from API named books and using map to transform the data for each book into a BookCard component that we created earlier. Each BookCard may or may not have a book cover, link, author, publisher, and so I created some conditional rendering utilizing ternary statements. I also replaced the missing book covers with the book SVG I imported earlier in the App.js.

I also added an error catch if the API call is unsuccessful in the fetch, and it will update the isError state and conditionally render an error message.

Here is the end of the App.js component. Here we have the main container div: I import the Search.js component and pass in the props.

Next, there is a ternary that checks if isError is true and searchTerm.length is greater than 0, then it will respond with an error stating that there are no results for that search term. This will also not allow the cards-container div to render if true.

Nested inside the first ternary is another ternary in the cards div, which checks if the API is loading is set to true to show the loading gif if it returns a response. We can call the state of books, which should return an array of BookCards created when the user clicks on the submit after putting in some text in the input field.

Let’s focus on creating the functional child components for App.js, the Search, and BookCard components.

Search Component

I begin the function with deconstructing props from the parent component (App.js) being handleSearchInput (which is what updates the state according to any changes in the input field as a controlled component), searchTerm, which is the value of the current state from the parent, and lastly, the handleSubmit which fires the API fetch from the parent once the user writes the search term and clicks the submit button to submit the form.

Book Card Component

On the left, I start in the same way. I deconstructed props for the BookCard component from the parent. The main purpose of this function is to structure the card that involves all the information required to submit this Chingu project for the second tier, and it includes the book cover, author, title, publisher, and a button that links the user to the hyperlink that provides more details about the book. The button has an onClick event handler, which changes the DOM window to the link attached.

HEROKU DEPLOYMENT

Install Heroku CLI.

The command below will reroute to the web to log in, or it will recognize that you already signed in to the browser and log you in automagically.

The build pack that you use will determine how the app will be set up to be deployed. When I first went to the Heroku documentation, I only saw the node.js build pack, and my app couldn’t be deployed. Make sure to build with the following build pack for your create-react-app.

You may come across an error if you have both package.json or .yarn file. I usually remove the .yarn file and rerun the command.

Once you run the command above, you should click on the Heroku link, and your application should be deployed online! If you want to see more details, you can log in to Heroku in the browser, and you should be able to see your app, the build package, and add API keys if you need to.

Thank you for reading! I hope you found this blog to be helpful.

--

--