Conditional rendering in React with catamorphisms.
Tags: react, catamorphism, javascript, render
Published: 2019-05-04 21:15:20

---
title: Conditional rendering in React with catamorphisms.
published: true
description: Conditional rendering components using catamorphisms in React.
tags: react, catamorphism, javascript, render
---


Do you ever look at your React components and think to yourself, there has got to be a better way to handle these conditions inside my components.

When I was first introduced to functional programming. One of the "rules" imposed was to never use `if / else / else if`.

This presented a huge issue for me. How can I manage this. Also, how can I manage this in my React Components?

Lets first look at an example of what I am talking about.
Below is an example of checking a variable and then returning the correct component.

The same result can also be achieved using a switch statement.

```javascript

import React from 'react'
import Doberman from './Doberman'
import Chihuahua from './Chihuahua'
import BullDog from './BullDog'

const Dog = breed => {

    if(breed === 'Doberman') {
        return <Doberman />
    } else if (breed === 'Chihuahua')
        return <Chihuahua />
    } else {
        return <BullDog />
    }

}

```
So, whats wrong with this? 

In my opinion, its ugly. 

It is not safe. `breed` can come back as undefined or better yet some other breed of dog. 

Also, in this example we are adding logic to our UI components, which is challenging to test.

So lets talk about how Catamorphisms can helps us manage these conditions in a different way.

## Catamorphism

> [Taken from Wikipedia](https://en.wikipedia.org/wiki/Catamorphism)
> In functional programming, catamorphisms provide generalizations of folds of lists to arbitrary algebraic data types

For those new to functional programming, fold can also be referred to as reduce or aggregate.

Say our application needed to determine the breed of dog, and then render the corresponding component to its user. In order to implement a catamorphism we would need to identify all the breeds of dog we would expect. 

Here is an example of our list, that will support a catamorphism.


```javascript

import daggy from 'daggy'

const DogBreed = daggy.taggedSum('DogBreed', {
    Doberman : [],
    Chihuahua : [],
    BullDog : [],
    Unknown : []
})

```

[Check out daggy here](https://github.com/fantasyland/daggy)

Our application would need to have an initial state defined. Inside our initial state we would assign our dog breed. Lets have a look...

```javascript

const INITIAL_STATE = {
    dog : {
        breed : DogBreed.Unknown
    }
}

```
Since our application has not yet loaded, and we do not know what our dog breed is, we create an `Unknown` breed.

At some point in our applications lifecycle we would set our dog's breed.

Lets have a look at this example of setting our dog's breed using this super cool FP library Pratica.


```javascript

import { Ok, Err } from 'pratica'
import daggy from 'daggy'

const DogBreed = daggy.taggedSum('DogBreed', {
    Doberman : [],
    Chihuahua : [],
    BullDog : [],
    Unknown : []
})


// DogBreed.is 
// A useful built in type check when using daggy.
const isValidBreed = breed => DogBreed.is(breed) ? Ok(breed) : Err()

// Safe function with no side effects. 
export const getBreed = dog => Ok(dog)
    .chain(dog => Ok(dog.breed))
    .map(breed => breed === 'Doberman' ? DogBreed.Doberman : breed)
    .map(breed => breed === 'Chihuahua' ? DogBreed.Chihuahua : breed)
    .map(breed => breed === 'BullDog' ? DogBreed.BullDog : breed)
    .chain(isValidBreed)
    .cata({
        Ok: breed => breed,
        Err: () => DogBreed.Unknown
    })

```
Let me take a second to talk about what is going on here. 
Im using the `Ok` monad to check our dog object.

1. We pass our dog into our `Ok monad`

2. Next step, we `chain` chain allows us to unwrap our Ok Monad. 
    a. Then set another Ok monad to check for `dog.breed`. 
    b. If `dog.breed` is undefined our Ok monad will return Err and will pass straight to our `cata.Err` where we set `DogBreed.Unknown`.

3. We then pass the into a `map`. Map accepts the output of our`chain`, our `OK Monad`.
    a. Map takes an `OK monad` unwraps it and checks it and then and wraps it back into our`Ok monad`
    b. We map over every possible breed type. 
    c. If we find a match we set our breed. 
    d. If not we return type to our next map.

4. Our last check, `.chain(isValidBreed)`.
    a. Why do we need this? If the breed is not one we are expecting, we need to handle that case and defer to `Err()` which will default to `DogBreed.Unknown`
    b. We chain the result of our above maps into a function `isValidBreed`
    c. isValidBreed does a check on the breed. If it is of type DogBreed, we return an Ok monad with the breed. If not, we return Err()
    

Great.

Here, we show calling our safe `getBreed` functions that implements `pratica`.


```javascript

// a contrived example of updating our state...
const dog = { breed: 'Chihuahua' }

const state = {
    dog : {
        breed : getBreed(dog) // DogBreed.Chihuahua
    }
}

```

We are now ready to see this in action.
Lets remember the goal is using an alternative to if / else in our react components.

We will be passing `breed` to our Dog component. `breed` is now an instance of our `daggy` `DogBreed`. Meaning we can apply a catamorphism (cata) to it. The `cata` will resolve to its current type.


```javascript 

import React from 'react'
import Doberman from './Doberman'
import Chihuahua from './Chihuahua'
import BullDog from './BullDog'

// Lets remember here that breed is the result of `getBreed(dog)` which is a List we can apply a catamorphism on.
const Dog = breed => breed.cata({
    Doberman  : () => <Doberman />,
    Chihuahua : () => <Chihuahua />,
    BullDog   : () => <BullDog />,
    Unknown   : () => <div>{'Unknown breed'}</div>,
})

```
Daggy also supports the passing of parameters, which can also be quite interesting. [Check out daggy here.](https://github.com/fantasyland/daggy)