Boocket

Boocket is an app for book lovers that want to keep track of the books they want to read.    You can search for books in the Google Book database and add them to your personal wishlist. If you can find anything you like you can create a new book and add it to your personal list and delete it when wished. All books are persisted in the Boocket database, so you will have always your list with you!

I used the create-react-app generator to start my project and in specific npx, a npm package runner, a tool to execute node.js packages.

npx create-react-app google-bookshelf

*I have change the name of the app after that.

My JS files, components and containers

index.js file will have my store with Redux that is connected with the rootReducer and thunk, in order to use async actions. index.js renders <Provider /> as the top level component and wrap my <App /> component.

App.js renders <NavBar />, <Footer /> and it is responsible for the React routes too using react-router-dom. I use react-router-dom, that is react-router plus some link improvements, <BrowserRouter> and <NavLink>.

<SearchableBookListContainer¬†/>¬†renders a form and takes care of its ‘query’ state. After the query, it renders a link list of books. This container is connected to the store to dispatch the action of searching and adding an item to the wishlist plus a list created after our search, the searchBookList. The list rendered with the results of the search has nested links to the book itself. Inside Link¬†I¬† pass a pathname and a state with the book object and in my representational Book component I will get this info as props from Link react-router. I can access them as props.location.state.

<WishListContainer /> is connected to the store and gets the wishlist from here and renders it. It dispatch two actions, getMyWishList that fetches my API end point for a list of books and the deleteBook action. The list of books rendered follows same pattern as the one displayed in <SearchableBookListContainer />, and includes links to the book itself.
<CreateBook /> is a container connected to the store to dispatch the action of adding a new book and renders a form to create it.
<Book />, <Home />, <Footer /> and <NotFound /> components are representational components.
<NavBar /> takes care of all links importing from react-router-dom NavLink.

My source for the data is Google Books API. The Google Books API allows a maximum of 40 returned results and can sort only by search relevance and publish dates. I used the first functionality.

Using Redux and Thunk

Redux is a predictable state container for JavaScript applications. It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test.‚Ää‚ÄĒ‚Ä䬆https://redux.js.org/

I will use Redux to organize and have all my states in the same place and Thunk as a middleware to help me alter the behaviour of my actions, allowing me asynchronous requests. I will need to dispatch an action saying I am loading data, then to make a request to the API, and then to wait for the response and then dispatch another action with the response data.

With a plain basic Redux store, you can only do simple synchronous updates by dispatching an action. Middleware extend the store’s abilities, and let you write async logic that interacts with the store.¬†‚Ää‚ÄĒ‚Ä䬆https://redux.js.org/

To install Redux and Thunk in my app I type into my console:

npm install --save redux 

npm install --save react-redux

npm install --save redux-thunk

  1. Initialize my store in index.js using createStore Redux function and pass it down to my top-level <App /> container.

To have access to the store in any of our components we import the react-redux function connectinto the component where we want to have access.

If we want some state we can use:

We can access these data as: this.props.whatEverWeWant.

If we want to dispatch an action and update our store we do something like:

Then to be able to debug I have installed redux-devtools-extension and add this code to my index.js:

Considering web accessibility in my app

I have followed some requirements to take into account web accessibility.

  • WAI-ARIA ( Web Accessibility Initiative – Accessible Rich Internet Applications). I am using Aria HTML attributes.
  • Using as possible fragments <> </>to group together multiple elements and don’t break the HTML semantic.
  • Every HTML form control, such as <input> and <textarea> is labeled accessibly.
  • Create react app has the eslint-plugin-jsx-a11y plugin with a subset of rules activated that checks your code as you develop.

Using docker

I wrapped up the project as a docker image in the Dockerfile.

Creating my API

I follow these instructions and as soon as I have the basics working I do the following:

Create a model for my Book:

I create a seeds file and run my migration:

Generate my controller:

Create a serializer for book and draw my endpoint inside config/routes.rb

How do I connect my react app with my rails API? In my actions. I fetch the end point of my API “books” and GET and POST to it.

This is how my end point looks with my wishlist:

And I think that that’s it! I have enjoyed a lot this project despite it took my a¬† while to figure out Redux functionality. I went through a lot of different problems and learnt a lot. Ah, this bug was my favourite one . I manage to set undefined as my query so my search results were hilarious but very revealing too!

Leave a Reply

Your email address will not be published.