Integrating the Google Books Embedded Viewer API into a React App

Christina Sohn
3 min readDec 11, 2020

--

For my final project at the Flatiron School, I created an app called BookQuest, which motivates students to read books by providing rewards for the activities that they complete. In the app, students can search for books to read and mark a book as ‘Currently Reading.’ I implemented the Google Books API to show an embedded viewer that would display the book’s content. Integrating the embedded viewer to create a seamless user experience was the most challenging part of the project. I overcame these challenges with careful debugging in the console and collaboration with more experienced software engineers.

Styling for the Viewer Canvas

One of the challenges of working with the Google Books API was that I needed to translate the example code from vanilla Javascript into a React component. When I integrated the code into the React component, I found that the canvas to display the book content was not showing up. I solved the problem by using the developer tools to compare the page elements if I used vanilla Javascript versus using React. I found that when I inspected the page of the React component, the canvas viewer’s in-line style property did not show the correct dimensions for the viewer canvas. I discovered that React was overriding the styling for the canvas. I had to change the dimensions in the stylesheet for the content viewer to display on the page.

index.css #viewerCanvas{  
margin-left: 150px;
width: 700px;
height: 800px;
}

Reloading the Viewer when Rendering the Component

Another challenge I encountered with the embedded viewer was that if a user clicked on a button to render a different component and then went back to the book viewer, there would be an error that Google Books had not yet loaded. I sought help with this problem by posting an in-depth question in the Flatiron School Slack channel. I was able to collaborate with other members of the FS community to write two useEffect statements in the component: the first had an event listener to check that the script tag had loaded, and the second useEffect statement would run once the ‘loaded’ condition was met.

While that eliminated the error message, the book would still sometimes not show up when a user redirected back to that page. I sought further advice from a Flatiron School instructor who had experience with Google APIs. We worked together to deduce that we needed to create a new instance of the viewer each time the component rendered. Through independent debugging and collaboration with others, I was able to successfully adapt the Google Books embedded viewer to my React application.

Here is the final code for the React component:

const BookViewer = () => { 
// Obtain ISBN number of user's current book
const ISBN_num = useSelector(state => state.currentBookReducer.currentBook.book.ISBN_number)
const canvasRef = useRef()

// Initialize loaded state as false
const [loaded, setLoaded] = useState(false);
// Create alert message if book not found in Google Database
function alertNotFound() {
alert("could not embed the book!");
}
// Add a Google Books script tag and event listener if the tag has loaded useEffect(()=> {
const scriptTag = document.createElement('script')
scriptTag.src= 'https://www.google.com/books/jsapi.js'
scriptTag.addEventListener('load', ()=>setLoaded(true))
scriptTag.id = "google-script"
document.body.appendChild(scriptTag);
}, []);
// Once Google Books has loaded, then create new instance of Default viewer and load book's information to viewer useEffect(()=>{
if (!loaded) return
else{
if(window.viewer){
let viewer = new window.google.books.DefaultViewer
(canvasRef.current);
viewer.load('ISBN:'+ ISBN_num, alertNotFound);
}
else{
window.google.books.load()
window.google.books.setOnLoadCallback(() => {
let viewer = new window.google.books.DefaultViewer
(canvasRef.current);
window.viewer = viewer
viewer.load('ISBN:'+ ISBN_num, alertNotFound);
})
}
}}, [loaded])
return (
<div>
{loaded ?
<div>
<div ref={canvasRef} id="viewerCanvas"></div>
</div> :
'Script not loaded'}
</div> )
;}}

Google Books Embedded Viewer API documentation: https://developers.google.com/books/docs/viewer/developers_guide

--

--