maticzav
maticzav

Reputation: 962

Redux - Making Impossible States Impossible

TL;DR

Is there a library which makes something like Elm-Union Types possible in JavaScript with Redux and ImmutableJS?

Idea

Hi!

I am rather new to Redux, still exploring best patterns to use. I spent some time learning Elm and in Elm the core focus of whole application is the Model.

The core prinicple of Elm is making errorless applications. In comparison with JavaScript, Elm is packed with basic types (String, List, Boolean...) as it's also a static typed language. On the other hand you can use ImmutableJS and Flow and get pretty decent amount of full types and type check also in JavaScript, which makes this very even.

But the contrast between Elm and JavaScript comes with a feature called Union Types. With Union Types you can say something like:

type alias User = {
  name: String
}
type Session = LoggedOut | LoggedIn User

What this means is that we have two options when it comes to session:

This is extremely useful when dealing with "HOC" as we can say simply:

case session of 
  LoggedOut ->
    displayLoginButton
  LoggedIn user ->
    displayUser user

Furthermore you can use the same pattern when fetching data. When data is fetching the state is Fetching once it is fetched, the state is Fetched Data and in case of an error, the state is FetchingError Error.

This makes data very secure and very clean. The same problem written in JavaScript/Redux would normaly be tackled something like this:

const model = {
  loading: false,
  loaded: false,
  error: null,
  data: null
}

At first this might seem normal, but as you think you see that "impossible" situations can be encountered. For example:

const model = {
  loading: true,
  loaded: true,
  error: null,
  data: null
}

The data can't be loading and be loaded at the same time!

Question

Is there a way to acheive similar concept with JavaScript-Redux and still remain the immutability of ImmutableJS? Or if there's a way to rearrange the model to make impossible states impossible in Redux?

P.S.

Great talk about this in Elm: "Making Impossible States Impossible" by Richard Feldman

Upvotes: 3

Views: 430

Answers (2)

markerikson
markerikson

Reputation: 67567

No, there's nothing specifically built into React or Redux that enables that. That sort of thing is really more at the language level. You might want to look into TypeScript or Flow to add static types that help with that. Beyond that, you can probably put something together using an explicit state machine approach or careful reducer logic checks.

My React/Redux links list has a section on static typing tools that may be useful in getting started. In addition, since you mentioned the "loading states" example, the React and Ajax category in my list specifically links to several articles that discuss ways to handle that concept in TS, Flow, and a couple other solutions.

Upvotes: 4

maticzav
maticzav

Reputation: 962

You can hack it like this:

const Session = {
  LOGGED_IN: user => ({ type: 'LOGGED_IN', user }),
  LOGGED_OUT: () => ({ type: 'LOGGED_OUT' })
}

switch (session.type) {
  case 'LOGGED_IN': {
    viewUser(session.user)
  }

  case 'LOGGED_OUT': {
    viewLoginButton()
  }
}

Upvotes: 0

Related Questions