Simple Remote Data in Typescript
Tags: typescript, javascript, functional, showdev
Published: 2020-11-05 16:41:34

Introducing [_Simple Remote Data_ (SRD)](https://github.com/rametta/srd#-simple-remote-data), a [Static Land](https://github.com/fantasyland/static-land/blob/master/docs/spec.md) compliant TypeScript library for managing state from remote sources.

**SRD's** top features are:
- Only **549 bytes** minified and gzipped, that is ridiculously small!
- Built with **Higher Kinded Types** ([HKT's](https://en.wikipedia.org/wiki/Kind_(type_theory))) to allow Typescript to infer these complex disjoint union types.
- Static Land compliant!
- Made for React or any other JS based frontend framework.

## What is a _Remote Data_ type?

A Remote Data type is a kind of [discriminate union type](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions) in functional programming for managing the state of some data that is retrieved remotely and asynchronously, such as http response data, websockets, server sent events, reading a file, or any other async IO.

Remote Data greatly simplifies the 4 states of any IO operation - **initial** state, **loading** state, **failure** state or **success** state, by combining them into one pure union so none of these states can overlap and cause [impossible states](https://youtu.be/IcgmSRJHu_8).

## Why would I use a Remote Data?

To simplify your state model and prevent impossible states! SRD allows us to perform safe and pure computations on our data without redundant null checks.

It also allows us to cleanly represent our state in our UI applications by providing functions such as `match` which is our [pattern matcher](https://en.wikipedia.org/wiki/Pattern_matching) utility.

## How would I use a Remote Data?

Here is a popular use case in any React application - fetching data from somewhere and displaying it on screen, while also displaying loading states and error states if the fetch fails.

```jsx
import React, { useState, useEffect } from 'react'
import { SRD, notAsked, loading, failure, success } from 'srd'

const App = () => {
  const [rd, setRd] = useState(notAsked())

  useEffect(() => {
    setRd(loading())
    fetch('...')
      .then((data) => setRd(success(data)))
      .catch((err) => setRd(failure(err)))
  }, [])

  return SRD.match({
    notAsked: () => <div>Empty</div>,
    loading: () => <div>Loading...</div>,
    failure: (err) => <div>{err}</div>,
    success: (data) => <div>{data}</div>,
  }, rd)
}
```

_Without_ SRD, we would need to manually manage states for errors, loading and initial states separately - _with_ SRD the code is a lot smaller, easier to follow and most importantly, **safer**.

## What else?

SRD also provides a lot of great functions for accessing and modifying the data inside the Remote Data.

If we needed to modify the data inside a `success` we can use the popular `map` function to do so, it will allow us to run a function on the inside data without worrying if it's a `success` or not.

Here is a TypeScript React example for updating an object:

```tsx
const [rdPerson, setPerson] = useState<RD<string, Person>>(notAsked())

useEffect(() => {
  setPerson(loading())
  fetch('...')
    .then((person) => setPerson(success(person)))
    .catch((err) => setPerson(failure(err.msg)))
}, [])

const doubleAge = (person: Person): Person =>
  ({ ...person, age: person.age * 2 })

const handleClick = () => {
  setPerson(rd => SRD.map(doubleAge, rd))
}

return <>
  {
    SRD.match({
      notAsked: () => 'Empty',
      loading: () => 'Please wait...',
      failure: (msg) => `There was a problem: ${msg}`,
      success: person => `My age is ${person.age}`
    }, rdPerson)
  }
  <button onClick={handleClick}>
    click to double my age
  </button>
</>
```

And `map` is not the only thing we can do, [SRD](https://github.com/rametta/srd#-simple-remote-data) provides over a dozen more utilities for managing your SRD state!

I hope this article clarified the advantages of using a Remote Data type and how to use SRD, I encourage you to try it out! If you do, feel free to "Star" 🌟 the repo [on github](https://github.com/rametta/srd)!