Building Okayar (Part 3): UI Built in React

Arjit Jaiswal
10 min readDec 24, 2021

Let me start off with a disclaimer: I do not consider myself good at React. For a back-end developer, though, I’ll give myself a passing grade. So let’s unofficially call this edition: A back-end developer’s guide to building a UI in React.

If you are new to Okayar, you may be interested in the first two posts in this series. You can find background on the app and my back-end setup here and you can learn how I built the infrastructure to run Okayar here!

Let’s get started!

Why did I use React and why should you?

As a back-end developer, looking at a front-end repo is always terrifying. There’s just countless folders, 10 different file types in them, and extremely foreign looking code everywhere.

React, thankfully, is the most friendly framework I’ve used. Things just make a little more sense than usual. You can create “components” which are something like reusable modules to which you can pass variables to customize them. These variables come in the form of “props”, which a component can’t modify directly, unless it is also passed the function to set its value. And most importantly, every component is a function that returns some HTML DOM, which makes very clear what the purpose of it is. In essence, a React app is just a tree of functions that result in one large HTML DOM returned to the user.

That’s not to say that this was easy, by any means. I sat through countless youtube videos explaining React concepts and countless hours debugging the smallest details. I admire front-end developers even more than I did before; it takes a different kind of patience and relentlessness to write good front-end code.

I don’t have many nitty-gritty details on why React is better than anything else, since I’m not a front-end developer and wouldn’t be able to really understand the differences to other frameworks. It’s clearly the most popular though, as evidenced by npm trends over time:

Screenshot taken from: https://www.npmtrends.com/angular-vs-react-vs-vue

And really, to me it just made sense. Hopefully the rest of this post will make it make sense to you too :)

Quick aside: Typescript

Use it. Typescript is an extension of javascript that finally makes it strongly typed. I cannot stress enough how useful this is. Managing complex javascript code without explicit types sounds horrible. I seriously do not know how anyone wrote good javascript code without it.

Here’s just a quick snippet of some Typescript code. As you can see, you’ll have strongly typed variables everywhere in your code — function definitions, variable assignments, and anywhere else.

All it does to your React file structure is change .jsx to .tsx, and .js to .ts. And with that small change it’ll make your life much, much easier.

A React app is one big tree

When you create a React app from scratch (using, aptly named, create-react-app), there’s a few main files you end up with. The first and most important: index.tsx:

There’s a lot to learn from this snippet alone. This file holds the function that is at the very top of the tree: ReactDOM.render. It takes the components passed to it (React.StrictMode with an enclosed App) and renders it to the HTML root. Here we also get our first glimpse of how easy it is to plug-and-play components. App is something that isn’t defined in this file; we import it with one short line at the top, and then can use it however we want.

Let’s take a look at App.tsx:

Remember, I mentioned earlier that every component in React is a function that returns some HTML DOM. You can see it in action here. App() is returning a block of HTML to the call from index.tsx. This pattern can happen endlessly. You can have a component that calls a component that calls a component, and 50 components later one will return some actual HTML. And that’s how you build a page.

Various React features and why you should use them

I’ll try to take this section top-down through my app’s tree, and point out useful React features as I go!

React Router

Let’s take a look at my app.tsx, one level down from the top of the tree I mentioned above:

There’s 5 key components here. AuthProvider I’ll save for the next post in this series about auth. Then we have Router, Switch, Route, and PrivateRoute. These are the components that make up the React Router’s logic.

The important lines here are:

<PrivateRoute exact path=”/” component={OkayarHome} />

<Route path=”/login” component={Login}/>.

These lines do exactly what you think they’ll do. If you navigate to https://app.okayar.com, it will take you to the OkayarHome component, because the path will exactly match /. If you navigate to https://app.okayar.com/login, you’ll be taken to the Login component.

The most obvious question you might be asking: “Well what is PrivateRoute and how is it different from Route”? This is again auth related, but put simply, the PrivateRoute is set up to redirect the user to /login if they are not logged in. So, the way I’ve set up my app, if on any screen you are not logged in you will be sent back to the /login screen.

That’s basically it. If I wanted to create a user settings page for example, I could add another PrivateRoute with path /settings that sends the user to a different component. If I wanted to add an “About” page, I could add another regular Route with path /about that doesn’t require auth. Simple and useful!

Reusable components

I mentioned earlier that any component is like a reusable module. We saw this in the previous section with the ability to add unlimited PrivateRoute components as my app grows. The same applies to any kind of component in React!

One good example of this is reused components between my /login path and my / path. While these 2 paths should show different contents, I do want the theme and general feel of the website to be the same. Things like the background color, the header bar, etc. Let’s take a look at my Login component, and specifically its return block:

Notice that there’s 3 components here that are actually imported, and make up most of the return block. These are OkayarHomeComponent, PageHeader, and PageBodyWrapper. The first and the last of these are just styled components, which I’ll cover in the next section. You can see their code here:

The PageHeader, by contrast, is another functional component. You might have noticed that in our Login component, we passed an argument called hideLogout to the PageHeader. This is a prop, and allows us to reuse components while at the same time customizing them based on variables passed to them. We’ll cover this shortly too.

Point being is that OkayarHome, which is where / sends a user, reuses the exact same 3 components at the top of its tree. By creating reusable components, we’re able to cut down on repetitive code in our code base and keep things looking pretty.

Styled Components

A styled component is a component that needs no logic, and just returns a div with css properties. This is super useful; rather than making divs with ids, I can create a component and style it like the snippet below:

It can even be set up to accept props that change the css, which again contributes to more reusable components:

You just need to do a simple import to be able to use these: import styled from ‘styled-components’;.

Fun stuff like Conditionals via Props

Props are central to React, and I’m under no illusion that I’ll be able to explain them better than anyone else on the internet. They’re basically arguments passed to a lower-in-the-tree component, and their value cannot be modified unless this lower component is also passed the function to modify said prop.

The cool thing is we can use these prop values in various ways. For one, you could just display it in part of the HTML DOM the component returns. More interesting, though, is you could use the props for something like conditionally rendering some DOM.

For a Login screen, we obviously don’t want to show a “Logout” button. This wouldn’t make any sense. Let’s remember the way the Login component was rendering the header: <PageHeader hideLogout />. In this component invocation, hideLogout is a prop for PageHeader. Let me show you the function signature and the props interface for PageHeader:

The PageHeader function signature accepts one argument: props. This is common across every functional component in the app. Each one just accepts props; these props, though, can contain unlimited variables. We are using Typescript, which means we have to define the types of every single prop that the function will accept.

This is where the PageHeaderProps interface comes in. The purpose of it is to define the types of every single prop that the functional component will accept. This is again a common pattern. Every functional component RandomComponent that takes props should have a matching interface called RandomComponentProps. In this particular component, there is only one valid prop: hideLogout. We’ve defined it as a boolean, and also indicated it is optional by appending a ? in the props interface.

So, we’ve passed the prop value as true (implicitly, we could have also wrote out explicitly <PageHeader hideLogout={true} />). Now, how do we use this to hide the logout button? Take a look at line 42, where I say {props.hideLogout ? null : ____ }. This is a classic ternary operator. I use the prop, which is a boolean, to decide whether I should render null or the Logout button.

This simple line operator makes components super customizable based on props passed! Again this leads to more clean code; if we didn’t have this, I’d have to make 2 components with only the slightest difference.

React Hooks

I believe these are relatively new, at least the internet made it seem like it when I researched how to use them. They are so, so useful and they really make the code much easier to read. Let’s look at an example from the PageHeader component above:

const [settingsMenuAnchorEl, setSettingsMenuAnchorEl] = React.useState(null)

This is a fun one — settingsMenuAnchorEl is meant to be used to tell a separate Menu component which element it should anchor to when displaying. So, the value of this variable will actually be an HTML element.

React.useState is by far my most used React hook. It provides two values– the first is the variable I wish to use, and the second is a setting function for the variable. So, the value of settingsMenuAnchorEl cannot be modified directly. It must be set via the setSettingsMenuAnchorEl function. This function can be passed through prop after prop, however far in the tree I want to send it. And whenever it is called and passed an argument, it will set the value of settingsMenuAnchorEl.

The use of this setting function can be seen in the handleSettingsMenuClick function:

When the Settings button on the UI is clicked, the anchor for the menu will be set to the Settings button element, and therefore be opened attached to it.

Another useful React hook is React.useEffect. This is really useful, as I can tell React that it needs to rerun some specific code whenever one of many props is changed. Take a look at this example, from my home page:

The logic React uses is as follows: If any of [selectedQuarter, selectedYear, shouldRefreshObjectives, currentUser] are changed, then the fetchData function is run, which pulls in current data from the back-end. This is super helpful when it comes to the logic on my home page! If a user selects a different quarter or year, I want to pull the data for that given quarter. If the user changes, I should also re-pull the data. And if some component way down in my tree sets shouldRefreshObjectives to true, then my app will pull the newest data. It’s a great shortcut for running repetitive code based on changing props, another thing I love about React hooks.

There’s one more React hook that was important to this app which we will cover in the next post about auth — React.useContext.

React component libraries

No framework is complete without open-source libraries to jump-start developers. You may have noticed in the PageHeader file:

import { Paper, AppBar, Toolbar, Button, IconButton, Menu, MenuItem } from ‘@material-ui/core’

This is me importing tons of useful components from the Material UI library. There are a lot of libraries like this– Material UI is the one I used, created by Google. It’s the reason my website kind of looks like a Google form, but hey, you win some you lose some.

Conclusion

Man, front-end is hard. Everything I wrote here took a long time to figure out, but I’m glad I stuck with it. I hope that the contents of this article will be useful to some back-end developers. It’s a scary javascript world out there for us back-end-ers, but React starts to make it easier.

A great thing this React project gave me is confidence to be able to carry out front-end work in the future, whether from scratch or onto existing React codebases. It’s liberating to learn this side of the software world — I no longer feel constrained to relying on someone else for kicking off any application. It’s been a goal of mine to really be a full-stack developer, and this is my step 1 towards it.

Please let me know if I missed anything, or if you have any questions! I’d love to talk more about this and know that I didn’t quite cover everything in this article.

And stay tuned for my last post in this series! I’ll be talking about my Auth implementation using Firebase Auth and its integrations with both my front-end and back-end. See you next time :)

--

--