In this three-part series, I want to take a functional approach to building React applications.

There will be mathematical theory sprinkled throughout the series, and hopefully by the end of it you will pick up some useful techniques!

**Series contents:**

- Part 1 - Deconstructing the React Component
- Part 2 - The Reader monad and read-only context
- Part 3 - Functional state management with Reducer

In the previous post, we looked at React
through a more functional lens and rebuilt parts of the React component by using a *View*
box that contains the computation `Props -> Element`

.

There are two remaining React component API that I want to replicate: *context* and *state*. And in this post
we will learn how to add a **read-only context** for
our application using yet another box object.

So onwards and upwards!

## Motivation behind context

Say that we have a copyright notice View as follows.

In order for this View to be used in our application, we will need to pass the props `author`

and `year`

down from the root View.

As the number of props grow in the application, the more data we will have to manually pass down. Not only is this a tedious process, but it also means that the root View will need to take in every single prop as its own input just so they can be passed down to descendents.

But wait, there is a better way!

## Meet the Reader

Let’s start by defining a new *Reader* box that contains a computation of the type `Context -> a`

. What is `a`

here?
It really could be anything, but for now we can focus on computations that return a View.

The Reader defines one function `runReader`

that takes in the value of the context, and returns the result of the
computation.

Now, we can use the Reader like this.

Here, the Reader’s computation returns a View, which is our previously defined `copyrightNotice`

,
that has its input props contramapped from the Reader context. So, when we run the reader with a context value,
we get the value (View) out of the box, which we can fold down to get the final element.

Take a moment to let that sink in.

Now, just like we did with View previously, we can make the Reader a *pointed functor*.

Then, we can use `map`

to wrap the notice with a `<footer>`

tag.

## But what else can Reader hold?

Remember that the Reader contains the computation `Context -> a`

, where `a`

can be anything?

So far we’ve returned a View from the computation, but it can really be *any* value, even a *function*!

Let’s look at a function that changes the color of an element within a View.

We can wrap this up in a Reader.

To use this Reader, we need to run it with a context, then apply it to an element in the View.

Rather tediously, we have to run both readers before can apply the `colorize`

function to the footer view.

Of course, there is a better way to do this. And that is with the ** ap** function.

The `ap`

of a Reader will call its resulting *function* with the resulting *value* of another
Reader. We can visualize this like so.

This means that we can simplify our usage of `withColor`

to this.

**A bit of theory:**
The Reader is now an *Applicative* in addition to being a functor.

An Applicative `A`

must obey the following laws.

- Identity:
`A.of(x => x).ap(v) === v`

- Homomorphism:
`A.of(f).ap(A.of(x)) === A.of(f(x))`

- Interchange:
`u.ap(A.of(y)) === A.of(f => f(y)).ap(u)`

For the Reader just substitute `A`

with `Reader`

in the above laws.

We can verify that these laws do indeed hold in this test.

## Chaining the Reader context

Let’s consider another view for displaying the page title.

Now, say we want to read the `title`

from the context, just like we did for the copyright notice.

But, how can we use both the `header`

and `footer2`

together? Maybe we `map`

over the View inside
the `header`

?

This solution works, but isn’t ideal since running `combined.runReader`

returns yet another Reader.
Therefore, in order to get the resulting element out we will have to run the Reader *twice*!

Imagine having to use invoke `runReader`

once for each usage of the context. Such drudgery! Luckily
for us, there is a *much better way* to do this. We need to add the ** chain** function.

The `chain`

function takes in a function `f`

, similar to `map`

. However, `f`

for `chain`

is a function that takes the result from the previous computation as the *input*, then
returns another Reader from it. And when the resulting Reader is run, the context will be
passed to all of the chained computations.

This allows us to easily combine the header and footer boxes.

Indeed, we now only need to run the Reader once.

**A bit of theory:**
The Reader is now a *Monad*.

A Monad `M`

must obey the following laws.

- Left identity:
`M.of(a).chain(f) === f(a)`

- Right identity:
`m.chain(M.of) === m`

- Associativity:
`m.chain(f).chain(g) === m.chain(x => f(x).chain(g))`

The `M`

in our case is the Reader.

We can verify that these laws do indeed hold in this test.

### But what is a monad exactly?

You can think of a monad as any object that implements the `chain`

function, and obeys the monad laws.

Note that you may see `bind`

or `flatMap`

being used instead of `chain`

in other libraries or articles. They are usually
the same as `chain`

, and can be treated as aliases. You might also note a similarity between `chain`

and the Promise
`then`

method. They are indeed almost the same. However, in the case of Promises, the computation is not lazy, and has
an immediate effect when constructed, whereas the Reader does nothing until `runReader`

is called.

## Why didn’t you just *ask*?

Let’s define a helper function for our Reader monad.

Now, we can start the chain by *asking* for the context.

We will also add a helper for this dot-chain sytle of code using generator functions.

The `Monad.do`

function allows us to write “normal-looking” JavaScript code.

## Assembling all the pieces

Recall that the app from the previous post rendered a *message* along with some header and footer content.

Let’s use our new friend, the **Reader monad**, and provide some *internationalization* (i18n) support for
that “Hello ___!” message.

We’ll start by defining a message bundle and a `formatMessage`

function.

Now, we can create context-aware functions using `formatMessage`

.

Also, recall our three morpshisms on elements from the last post. We’ll use them in the app as well!

Finally, we can build our entire app as follows.

While we’re at it, let’s crank it *up to eleven* by styling the app.

When we render the app, this will appear on the screen.

The runnable source code for the full example can be found in this repository.

## Summary

In this post, we learned about *Applicatives* and *Monads* and created the Reader to provide read-only
context for our application.

In the **next post** we will wrap up this series by adding support for **stateful computations**. So stay tuned!

If you want additional resources on Monads, I recommend these.