Skip to content

Things you need to know in our Frontend (a.k.a Farewell gift from Kyubin)

Conor Brady edited this page Sep 16, 2021 · 18 revisions

React Hooks

Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don’t replace your knowledge of React concepts. Instead, Hooks provide a more direct API to the React concepts you already know: props, state, context, refs, and lifecycle.

I recommend watching this youtube tutorials to learn the basics. If you prefer reading, the React official website has well-written documentation for Hooks.

Feeling lazy? start with useState & useEffect since these hooks are like bread and butter in our functional components.

Feeling lonely? there is a chat community called Reactiflux. Join them and be part of the community!

TypeScript

TypeScript has many benefits over vanilla JavaScript such as optional static typing, early spotted bugs, predictability, readability, rich IDE support, fast refactoring, and so on and so forth. Long live and prosper TypeScript! 🖖

Start learning all about TypeScript here. (I know this documentation is overwhelming but it's worth reading if you want to really learn the language.) Also, check out its Utility Types, some of them are being used in our application such as ReturnType<Type> and Partial<Type>.

Redux

The patterns and tools provided by Redux make it easier to understand when, where, why, and how the state in your application is being updated, and how your application logic will behave when those changes occur.

Not familiar with Redux? check out their official website here.

Redux Toolkit

Redux Toolkit is suggested as best practice, simplifies most Redux tasks, prevents common mistakes, and makes it easier to write Redux applications.

This is the core library that we use in our application to basically handle all the Redux stuff such as creating reducers, actions, and selectors using their createSlice API. Also, note that our code structure is based on their advanced tutorial.

Want to know how we can mutate state in our reducers? (Normally you shouldn't and RTK just makes it seem like you can), learn more about how this works behind the scene.

React Router

React Router is the standard routing library for React. It has a simple API with powerful features like lazy code loading, dynamic route matching, and location transition handling built right in.

To learn more about the usage of this library including their declarative component API, check out their documentation here.

Detecting Location Change

We are using React Router's useLocation hook to detect URL query changes (ex. detecting station codes or time of interest changes in MoreCast) and we also use useHistory to update the query in the URL. Use MoreCastPage.tsx & WxDataForm.tsx as a reference if you need to implement a similar feature.

Code Splitting (Future work)

Instead of downloading the entire app before users can use it, code splitting allows you to split your code into small chunks which you can then load on demand, which would reduce the initial load time.

Seeing having more individual products reside in one application, I think Code splitting should be introduced in the near future. It's actually pretty easy to achieve this since the project was bootstrapped with Create-React-App. Learn how to implement route-based code splitting with this link.

Authentication with Keycloak

We are using keycloak-js to handle authentication through RedHat Single Sign-On. Check out web/src/features/auth/slices/authenticationSlice.ts to see how the authentication flow works in our application. We are using keycloak-js@9 as of writing but the Platform service team periodically updates the version so keep an eye on it because we need to update the Keycloak type definition (which is in web/src/types/keycloak.d.ts) that I copy over from this package. Need to update the type definition? Install the particular version of the package then find the type definition buried in node_modules then copy and paste into our type definition.

Fetching keycloak-js from RedHat SSO

We are fetching the keycloak-js with a script tag in web/public/index.html. The script is coming from SSO hosted in our OpenShift platform where it uses a specific version of Keycloak, which is why we can't just install the package as a dependency in our project.

Material UI

We are using Material-UI React library for component building blocks, which attempts to implement the technology agnostic, and similarly named Material Design. So whenever you create a new component, check out their built-in components to start with.

Hook API for styling

We are using their styling hook api called makeStyles to style our components. It has many benefits including theme nesting and dynamic styles based on props.

The following code snippet demonstrates how this hook can grab a theme color that's been initialized in web/src/app/App.tsx and set properties based on props passed on through useStyles in the component.

// web/src/components/ErrorMessage.tsx
const useStyles = makeStyles(theme => ({
  root: {
    color: theme.palette.error.main,
    marginTop: (props: Props) => props.marginTop,
    marginBottom: (props: Props) => props.marginBottom
  }
}))

Nesting selectors

Use this trick if you need to modify certain properties in Material-UI components. Use this file as a reference web/src/features/fireWeather/components/WxDataForm.tsx.

Tests

We test functions using Jest and business logic using Cypress. At least that's the idea. They run on one of our Github actions everytime when you create a PR or push more commits. Check out .github/workflows/integration.yml to see what else is running in our Github actions.

Cypress & Coverage

The current coverage is based on solely Cypress tests. While we have pretty good coverage, this doesn't automatically mean all the business logic has been covered. For instance, when we test graphs we make sure there is a correct number of graphics displayed based on the fixture data. If I remove these checks Cypress will still think the graph components are covered because as long as graphs are displayed in one of our tests, it's been "covered". So I'd encourage you to write as many tests that are business logic related.

Graph with Plotly.js

Initially, we started with d3.js for our graph library, however, we found that it has a steep learning curve and required someone with the knowledge to keep maintaining it. So we decided to switch to Plotly which is built on top of d3.js and easy to work with (relatively). While it provides great functionalities and convenience, there is a trade-off. Due to the nature of our graphs displaying lots of stuff and my belief on their React components not being optimized properly (maybe they are trying their best who knows), it slows down the browser when rendering these graphs. We can perhaps mitigate this issue by displaying only a handful of graphs initially and hide the rest and then let users open what they want to see.

Side note: I created a small example on how you can use React with d3.js properly. Use this as a reference if you ever need to go back to d3.

Scatter traces

We display our graphs with Plotly's scatter traces. Use this documentation as a reference when you need to know more about all the <Plot /> component API.

Map with Openlayers

We have a couple of React components that are built with OpenLayers library (check out web/src/features/map/VectorLayer.tsx as an example). These components are based on this lovely Github repository. Get familiar with useContext hook before jumping into implementing a new OpenLayers component.