Composing components with PureScript Pux

Posted on August 15, 2016

PureScript Pux

Pux is a PureScript interface to React. The tutorial at http://www.alexmingoia.com/purescript-pux/index.html gives a good introduction to the library. The section titled Multiple components shows how you can easily compose simple components. What it does not show however is how to compose components that have effects (eff or aff).

I battled with this for a bit and so decided to document the solution in the hopes it helps other beginners. The explanation below shows how to compose components in the framework of the starter app.

I’m assuming that you have read the pux tutorial at least up to the fetching data section so I wont be covering the same detail here.

The starter app

The starter app has a counter component that is rendered in the Laout.purs file

The original counter

The original layout

Making the counter effectful

EffModel

The type of an update function with no effects (as above) is

For it to be effectful it should return an EffModel. The EffModel looks like this

The update type will then be

Changing the counter

To keep things simple I’ll make the counter component act as if its effectual without doing any actual IO. To perform effects the component returns a list of effects that should be performed in the EffModel’s effects. The counter needs to do three things

  1. Increment
  2. Decrement
  3. Apply the effects

The increment and decrement cases return a ReceiveInc effect that will then be passed to the component and applied by the ReceiveInc case. In a real world component there would be an actual IO action e.g. using AJAX with affjax etc. But ultimately you are returning the effect in the array to be applied.

Changing the layout

The layout’s update function must also be changed to use an EffModel

The problem is that the counter’s EffModel does not have the same type as the layout’s EffModel, so you can’t simply use the result from the child components. Rather you need to map both the state and the effects using the mapState and mapEffects functions.

So first the Counter’s update function is called. Then the state is mapped to change the state. Finally the effects are mapped by creating a PostCounter instance for each event. This can be cleaned up a bit, e.g. using the # operator

The final layout code looks like this

Changing main

The only remaining changes are a few minor modifications to Main.purs

  1. Import Network.HTTP.Affjax (AJAX)
  2. Add AJAX to the AppEfects type

  3. The update function no longer needs the fromSimple

Summary

The full code for this example is available in this fork of the start app https://github.com/andrevdm/pux-starter-app-with-effects

  1. PureScript By Example. The PureScript book
  2. Pux Tutorial
  3. Pux blog sample project. Shows this and more in a real world project. This helped clear up some of the confusion for me, definitely worth taking a look at
  4. Haskell Programming from first principles. Invaluable if you are new to PureScript/Haskell
  5. Source code for this example. Diff on d621094abb4cb3a9bea2b1a831d50fbc5ef014a6 will show changes made for this post.