Eugen Sawitzki
comsystoreply
Published in
4 min readMar 15, 2022

--

Switch statements replace long if-else chains. They make it easy to return different results depending on the value of some variable. Also, they are commonly used in React if you want to render different elements depending on the current state of your application. And that’s perfectly fine.
Problems arise as soon as you start overusing them. When you create functions that use the same switch statement over and over again. This is the point where tools for static code analysis start complaining about increasing cognitive complexity and decreasing maintainability. Especially if you additionally have nested conditions.
The most common suggestion for getting rid of switch statements is using polymorphism. See refactoring.guru or Refactoring.com. As React follows more the functional programming paradigm than the one behind OOP we need to apply a different solution. Namely dictionaries.
This blog post will show you how to refactor an application from using multiple switch statements to one dictionary, therefore decreasing the cognitive complexity and increasing the maintainability.

Let’s look at the problem

The following application represents a simple registration flow.

Simple application representing a registration flow

Each page has one input field. You can navigate between the steps using the NEXT and BACK buttons. In the end, you can submit the data you have entered.
So, depending on the currently active step we have to decide which component to render in the content area, whether to show/hide the BACK button, which condition to use for enabling/disabling the NEXT button, which text to show on the NEXT button, and what exactly should happen when you click on one of the buttons.
The code could look like this:

Full code of the application using multiple switch statements

You can see that each of the above mentioned features uses the same switch statement in order to tell the application how it should look and behave in each step. In addition to this, there are special conditions in the returned JSX also depending on the value of the activeStep state variable.
Imagine adding an additional step. You would need to touch all these places. Also, your IDE would not tell you which occurrences of the switch statement are not exhausted. This means whether you have implemented a case for each of the possible values of activeStep. There is a way to enable this in TypeScript using the never type (see this blog post). But again, additional code and additional complexity.

Let’s solve the problem

Now let’s have a look at how this problem can be solved utilizing a dictionary. In TypeScript, there is the type Record<Keys, Type>. This type defines a dictionary of values of some defined type that can be accessed via a key. Whereas the type of the keys has to satisfy the constraint of being convertible to string | number | symbol. In our case, we will use Enums.

In order to get rid of all the switch statements and conditions, we will create a dictionary with keys of the type Steps (the same Enum we use for the activeStep state) and values of the type StepConfig. The latter will hold all the elements which differ per step.

Types used to create a dictionary of step configs

Each entry of the dictionary represents a config with the needed elements for each possible value of activeStep.

Dictionary holding all step configs

We can now retrieve the config for the current step using the bracket notation with the state variable activeStep.

Retrieving the step config for the current step

This leaves us with the following code without a single switch statement or condition. The stepConfigs dictionary provides the correctly configured elements for the active step. Additionally, there are two utility functions that help us avoid describing the common properties of the BACK button (renderBackButton) and the NEXT button (renderNextButton) repeatedly.

Full code of improved application without switch statements and conditions

Adding new steps is a lot easier as well, as there is now only one single place that needs to be touched, besides adding a new value to the Steps Enum. Also, your IDE will show a lint error if you don’t implement a config for each of the Enum’s values, making it easier to catch mistakes early.
If I remove the config for the third step, I will get the following error message.

Error message in case of not implemented key

This blog post is published by Comsysto Reply GmbH.

--

--

comsystoreply
comsystoreply

Published in comsystoreply

Innovation through insight. Thinking lean and moving agile when delivering software products for the digital era.

Eugen Sawitzki
Eugen Sawitzki

Written by Eugen Sawitzki

Software-Developer at Comsysto Reply GmbH in Munich, Germany