Go & React: A 1, 2 Punch Combo
I recently had the opportunity to explore the combined capabilities of Go, Gin, and React for an interesting interview assessment. This post is about that journey and the steps I've taken after its completion. If you want to see the updated React page that was written for the assessment, you can find it hosted on my website here. You can also find the React source code located in the same repository that is used for this website here.
The basis for the assessment was that I had approximately 8 hours to write a website for a theoretical realtor company that allowed for two requirements, a secured user that could create, edit, and delete house listings and an unsecured search feature for listings. The listings were given a pre-defined set of fields, including photos. To accomplish this quickly, I decided to use my pre-existing Go/Gin server to host a new React application that uses my S3 bucket, that's behind a CloudFront CDN and Route53 CNAME record, for image hosting and a DynamoDB table to store the necessary information for each listing. The state this article and the related website are in as you are reading this is not the same as it was when the assessment was turned in.
So Why These Frameworks/Libraries?
At this point you're probably wondering why I chose these particular tools over similar ones that are currently available. Largely this was decided by two factors, the first being my prior work experience with the company I was interviewing with; which let me know that they like to use the React library for frontend development. I should mention that the assessment made no mention of what tools to use to complete the requirements. The second factor was that since I already had a Go/Gin server set-up that could handle proper https traffic, I wanted to showcase the skills necessary to maintain and improve such a setup. One of the nice things I had pre-existing knowledge of, from a previous assessment, was that it is really easy to serve built Javascript libraries from a Go/Gin server. Here is the one additional function needed to get the React to be served from this existing website.
// LoadStaticFolderRoutes loads all api routes that serve a static server folder.
func LoadStaticFolderRoutes(server *gin.Engine) *gin.Engine {
server.Use(static.Serve("/public", static.LocalFile("./public", true)))
server.Use(static.Serve("/realtor", static.LocalFile("./realtor/build", true)))
server.Use(static.Serve("/realtor/new", static.LocalFile("./realtor/build", true)))
server.Use(static.Serve("/realtor/search", static.LocalFile("./realtor/build", true)))
server.Use(static.Serve("/realtor/listing", static.LocalFile("./realtor/build", true)))
server.Use(static.Serve("/realtor/my-listing", static.LocalFile("./realtor/build", true)))
server.Use(static.Serve("/realtor/my-listings", static.LocalFile("./realtor/build", true)))
return server
}
If at this point you are still not convinced that these were good choices, here are some general facts about each one that should help close the gap that exists in convincing of you:
React Facts:
- It's not a framework, it's a library of classes; an abstraction.
- Writing html inside javascript allows dynamic content creation.
- Using components, one can easily breakdown complex front-ends.
- Passing props to components populates them with custom data.
- React supports type systems through propTypes. (bool, string)
Golang Facts:
- The designers were strongly motivated by their dislike of C++.
- Go provides static typing similar to C but with simpler syntaxes.
- Even with typing, you can use := to declare vars without types.
- Go routines are concurrent threads in the same address space.
- Channels provide complex communication between go routines.
Gin Facts:
- Gin is a web framework written in Go that performs really well.
- Developers save a lot of time from using common encapsulation.
- Excellent middleware support means tons of libraries to use.
- HTML templates give similar dynamic content delivery to React.
- Gin's Go roots provide good json processing support for APIs.
Designing the React Components
HTML builds up a majority of the web applications everyone uses nowadays. React components allow us to wrap up small sections of HTML and put them into individual classes with all the benefits of member variables and functions; in Javascript. Most developers will understand when I say that Javascript is not the first language college professors talk about when it comes to topics like Object Oriented Programming. When writing the website for this assessment, I built all of the content into 10 unique components. You can find a general, grouped description of the components below:
App.js, Main.js, & NavBar.js.
This is the main starting point for all access to the react application, requests are funneled through here. Most login logic takes place here and the navbar attaches to this render function before the page router starts its real definition.
Tile.js & TileDeck.js.
These components help make the root/search pages. TileDeck takes an array of JSON objects to send to Tiles for rendering. I want to improve the row/column based display order of the individual Tiles in a TileDeck.
Home.js & Search.js.
Both of these use Tile.js/TileDeck.js by making API calls to pass an array of JSON objects through their state and into the child components through props. Search.js takes text input and finds exact matches in state.
Listing.js, MyListing.js, and MyListings.js.
The three components here make up the add, edit, and delete capabilities of the listings. MyListing.js uses Bootstrap and an HTML Form, along with conditional rendering, to allow users to either add or edit listings.
Together, these components make up what is known as a single page application. Below, you can find a quote about these types of applications from Pete Hunt; one of the original members of the Facebook team that built and open-sourced React:
“Single-page applications” are all the rage these days. These are web pages that load once, and when the user clicks on a link or a button, JavaScript running on the page updates the address bar, but the web page is not refreshed. Management of the address bar is done by something called a router.
https://github.com/petehunt/react-howto
Was the Go/Gin really used?
Yes! Almost every modern frontend needs to make API calls to send and receive the necessary data for their day to day operations. This assessment needed 4, 2 GET requests and 2 POST requests. The GET requests either return all active listings in the database, including soft deletes, or a single listing based on the MLS parameter passed to the API call. One POST request is for adding/modifying listings and the other is for uploading images to the S3 bucket for public viewing. Thankfully with this project's recent transition to go modules, it was really easy to refactor the organization of the project's go code into more distinct files. Now there is one src folder with two sub-directories containing the models and handlers for both my blog and the realtor website in independent files. This is how easy writing APIs can be using Gin:
//ListingsGETAPI : Gets All Realtor Listings
func ListingsGETAPI(c *gin.Context) {
c.Header("Cache-Control", "no-cache")
listings := models.GetRealtorListings()
// Call the JSON method of the Context to return the results
c.JSON(200, listings)
}
//ListingGETAPI : Gets A Realtor Listing
func ListingGETAPI(c *gin.Context) {
c.Header("Cache-Control", "no-cache")
if listing := c.Param("listing"); listing != "" {
card := models.GetRealtorListing(listing)
// Call the JSON method of the Context to return the results
c.JSON(200, card)
} else {
empty := []byte(``)
// Call the JSON method of the Context to 404
c.JSON(404, empty)
}
}
Hopefully now, as the reader, you are starting to understand how powerful Go, Gin, and React can be when used together; if the wielder has the right knowledge. I hope to do some follow-up soon about things that can be done to improve this React project further. Topics might include: eslint/linting, code styling, and testing.