Working at the best point in React

Nandhika Prayoga
11 min readApr 28, 2020

React is a great framework and becomes more popular day by day. There are also other competitors such as Vue and Angular, and yeah both of them are great frameworks too because they have their own benefits compare to the React, but I have no experience to use either of them so we are going to focus on React only. I’m using React because it’s my first mate to meet when comes to the front-end for the first time. I love making anything on front-end such as animation, component, and making helpful tools to boost the effectiveness of daily activity as a front-end developer. I prefer not to use any library/tools out there as possible if I could make one, particularly when creating a component because it helps you to more understand your code, have originality, and freely do anything creatively without any restriction. Thanks to Facebook, React comes to save humanity by fulfilling my needs in front-end. Now, React is more powerful after React officially introduces hooks in 2019.

I assume, at least you ever experience use React even only just initialize React App. Because in this article, I will share with you how my team deals with React in best practice, including hooks as a new system in React. Enjoy!

The language

As far I know, React only has two languages to pick, namely JavaScript, and TypeScript. Let’s see the comparison between them.

Cumulate from https://smthngsmwhr.wordpress.com/2013/02/25/javascript-and-friends-coffeescript-dart-and-typescript/

There are more characteristics that I can show you actually, but let just focus on these two keys characteristics. From this information, it’s actually 50:50 to choose one of them, why? If we are talking about a big project, working on a big company as a software developer/engineer, then having scalable and maintainable codes is so important right or you don’t care about it too much so you prefer to the faster compilation time language since perhaps your application is disposable.

Typescript helps a lot of JavaScript developers in order to achieve maintainability by doing type checking to ensure the integration of all systems. But on another side, TypeScript is a slow compilator since we need to do type checking compare to the JavaScript. Because of that, comparing non-typed language and typed language is not suitable in terms of compilation time, should compare typed language to the other typed language as well.

If you ever experienced to use typed language before such as Java, you know how hard it is to code compared to doing so on Python or JavaScript. But in the end, with/without you realized that typed language has more bug escaping when comes to running time since it has covered the bug in the compilation. This is it! This is why typed language is more maintainable, you don’t want to your clients witness annoying bugs because of uncaptured bugs in the compilation time, right? Don’t you?

Since we only have two options, and because of all these reasons, without a doubt we chose TypeScript as the main language to develop React Application even it has a slow compilation. Actually, type checking time is still a tolerance time since the main code has much computation and only does it once in production. From personal experience, actually there is no big difference between TypeScript and JavaScript in compilation time, nothing to feel, so don’t worry about it. Also, many developers currently adopt TypeScript for their application because of the same reason. In the end, perhaps TypeScript will be popular than JavaScript.

Programming Style and Common Techniques

There are a lot of developers who still used old techniques, particularly on array manipulation. Many a sustainable company that has JavaScript or TypeScript source codes already dumped the old techniques and also they try to adopt functional programming as possible when works on React.

React itself is almost use functional programming, seen from no mutation but only constant, use composition for component hierarchical, and function-oriented since React already used hooks. In order to synchronize to the project, we also need to adopt functional programming as possible, here is how we did.

Use constant

We always try to use a constant as possible, because React should have no mutation at all.

All variables are constant

Not only just variable to be constant but also a function is a constant.

Array manipulation

Manipulate an array could be conducted by for-loop or where-loop, that’s a traditional way and tends to confuse when it has a complex manipulation. This is how we did it by using a filter method and a map method. a filter is used to get values that we interest in only, and a map to map each element into a new element.

Snippet code of components

So we do have a list of values and want to show it on the page in good looking. But before that, we need to limit the values, so what we did is filter the values and then map the filtered values. Pretty straightforward, right?

Actually, there is another function in the context of array manipulation, namely, a reduce method, to extract information from each element and cumulate all of them into something. All of these array manipulation functions are actually high-order functions, which is one of the functional programming patterns.

Magic Syntax for Object and Array Merging (more)

JavaScript/TypeScript has a little different when comes to merging. Let’s see!

const newCache = {
investigationCaseFormData: {
...global.cache.investigationCaseFormData,
referenceCase: newReferenceCase,
referenceCaseId: newReferenceCaseId,
},
}

This is an example of a cache in our application, if we want to edit the cache, we could copy global.cache.investigationCaseFormData first and then edit it by adding new reference_case and new reference_case_id.

const newTableData = [
...tableData
...newData
]

Snippet code of Table component in the Web. As you can see we merged two different array lists.

Composition

This is one of the functional programming patterns and used by React to see all components. In another side, we as a developer must support it by doing composition for all the components we have. Don’t worry about this stuff, by you knowing or not you definitely will do so when working with React.

Example of the composition. It’s actually the same as we did when code pure HTML.

<Title>
<Box
axis={Box.Axis.Vertical}
crossAxis="flex-end"
>
<Text isBold={true} fontSize="6vw">TBCare</Text>
<Text isBold={true} fontSize="6vw">PPTI</Text>
</Box>
</Title>

Hooks: Perfect case you could use

Since we use new React and TypeScript as a language, let me share with you how we use hooks in the best way. Note, to use React Hooks at least you have React 16.8.

There are 5 types of hooks that we used as the following:

  1. useState —A function to define a simple state
  2. useEffect — A function to call another function (callback like) whenever there is an event (effect)
  3. useReducer — A function to define a complex state and separated from an existing component
  4. custom hook — A custom hook that we created to utilize development
  5. useContext — A function to get state from ancestor component

Looking at a definition it’s never actually a good picture to understand. Let’s see how we used it.

useState

Normally we used useState whenever it is a just normal state, there is nothing need to tackle, just a state. Let’s see, we have a Field component, inside the Field component we need to save a value, whenever the user changes value from input then we need to change the value as well. This is how it looks like

import React from 'react';
import { Box } from 'components';
function Field({
value = "",
//... other props can't be shown
}: FieldProps) {
const [innerValue, setInnerValue] = useState(value);
// ... other stuffs return (
<Box>
// ... other components
<StyledField
value={innerValue}
onChangeText={newValue => setInnerValue(newValue)}
// ... other props can't be shown
/>
// ... other components
</Box>
)
}

useState there accepts one parameter that is initial value and then in return gives you a value that you just initialized and the setter function of the value.

How do we work on this? So we used innerValue on the input component which is StyledComponent, onChangeText will give a new value through newValue when there is new input from User, and then setInnerValue will set that newValue to innerValue. Finally, the Field component will be rendered for new value. Simple as like that.

useEffect

Next is useEffect, used to see an event and do something about it, it pretty much only does so. The event we are talking about here some variables that have changed. Let’s see how we used it on the Field component.

import React from 'react';
import { Box } from 'components';
function Field({
value = "",
//... other props can't be shown
}: FieldProps) {
const [innerValue, setInnerValue] = useState(value);
useEffect(() => {
setInnerValue(value)
}, [value])

// ... other stuffs
return (
<Box>
// ... other components
<StyledField
value={innerValue}
onChangeText={newValue => setInnerValue(newValue)}
// ... other props can't be shown
/>
// ... other components
</Box>
)
}

See a new things just added? There is a useEffect there. This is a short documentation of the useEffect:

  1. The first parameter — The function will be called when there is an event
  2. The Second parameter — List of variables is watched to see there is a change in one of them (if there is one changed then there is an event).

We are using this useEffect to see if value of the Field from outside is changed, then we need to synchronize between two values (value and innerValue) by useEffect. It’s like forcibly to change innerValue from outside regardless of what innerValue looks like on Field. That’s it all about useEffect.

useReducer and Custom Hook

Back to the useState, I mentioned useState is a simple technique to work on simple state. Some of you wonder, how a complex state looks like? a complex state can be seen by how you set the value in different ways. Fortunately, we have one a complex state on the project, that is form state. So besides we have Field component we also need form state to validates the input. We actually wrapped useReducer in custom hooks, so here how the code looks like part by part.

The custom hook (main part)

Custom hook

Manipulator, used by useReducer when there is a setter action.

Manipulator used by useReducer to update the state

I know there is a lot of going on here. I want you just focus on first image line 118–134, that’s how we used useReducer that accepts two parameters:

  1. The first parameter — Manipulator function will be called when there is action
  2. The second parameter — Initial value

The manipulator is shown on the second image. Notice we used switch-case, so inside it we set the value of form in two different ways and switch-case is used to pick one of the ways. The actions are:

  1. Update new value on a specific field
  2. Update isValid on each field by validating all the fields

That’s how we worked with useReducer. Not only that, but we also implement that in custom hook, useFormState, defined as a form validator. Notice we use the same prefix as other hooks, namely use-, yes it’s intentional because React suggests using this prefix as a convenient and conventional way.

useContext

For experienced React developers, you know how hard it does state management between two components with a big gap. For instance, you want to share states from grandfather component to your beloved child component, then one of the options is you do propagation through props from top component to the low component on the tree. It’s a bad idea since you just avoid low cohesion. Some expert suggests Redux, actually, it’s not quietly a perfect tool to tackle the problem in current React that has Hooks. Let me show you why after the explanation of useContext!

Thanks to React now we have useContext, it helps you by not doing propagation through props that let your components have high cohesion. In our project, we used useContext only once, to deliver global states to all components inside the tree. This is how we defined that by useContext.

import React from 'react';
import { ThemeProvider } from 'styled-components';
const theme: ThemeProps = {
colors: {
totallyWhite: '#FFFFFF',
almostWhite: '#FAFAFA',
gray: '#5F5F5F',
mediumGray: '#C2C2C2',
lightGray: '#EFEFEF',
red: '#9A3838',
green: '#0DCE66',
black: '#454545',
},
};
export default function App() {

// Other stuffs we defined here

return (
<ThemeProvider theme={theme}>
// other components
<Router>
<Home />
</Router>
// other components
</ThemeProvider>
}
}

Working on React actually can be a different paradigm to styling. On this project, we don’t use CSS or SCSS, we used styled-components since it’s easier to share common variables, and at this rate, we want to share consistent colors. So here it is, a snippet code is a pretty straightforward right? You defined your themes and then put it on ThemeProvider. Keep in a note, There is a Router component between ThemeProvider and Home for next reference. Also, this is only the first part, the provider.

We are going to see another part, the consumer (last part)

import React, { useContext } from 'react';
import { ThemeContext } from 'styled-components';
export default function Home() {
const { colors } = useContext(ThemeContext);
return (
<Box
width="100%"
axis={Box.Axis.Vertical}
>
<Content title="Statistik Kasus Per Wilayah">
<Box
width="100%"
padding="48px 24px"
mainAxis='center'
crossAxis='center'
borderRadius="3px"
background={colors.totallyWhite}
>
// ... other components
</Content>
</Box>
)
}

Simple right? you get the colors. then used it on component, at this rate we used it on Box component for the white background. Also, you notice in the provider codes between ThemeContext and Home there is Router component, we don’t need to involve the Router for propagating the states, there is no need the Router needs to know the state of colors at all, Router only knows what its responsibility on Tree. This is why useContext is used to be.

Now you understand how useReducer used to be and useContext could tackle state management with a big gap. Redux is actually just useReducer + useContext, since that problem could be tackled by useContext only then that’s why we don’t need the full part of Redux to tackle the problem. That’s actually the reason why we don’t use Redux on the project because we could do pretty much everything with Hooks, thanks again Facebook!

Takeaways

Working on React actually is functional-oriented, since the React itself uses functional programming even though it’s not completely functional because React needs to modify DOM (mutation). I strongly suggest you learn about functional programming, it’s a good thing to learn or a new good step while developing scalable and maintainable React application. I hope you get this finish line by going through all my writing and get more sense to work better on React application, thank you!

--

--

Nandhika Prayoga

Mainly a Full-stack Developer, Software Architecture Engineer. I'm a passionate developer, love to learn new things and write an article about it