Join egghead, unlock knowledge.

Want more egghead?

This lesson is for members. Join us? Get access to all 3,000+ tutorials + a community with expert developers around the world.

Unlock This Lesson
Become a member
to unlock all features

Level Up!

Access all courses & lessons on egghead today and lock-in your price for life.


    Create State ADT Based Reducers

    Ian Hofmann-HicksIan Hofmann-Hicks

    The typical Redux Reducer is function that takes in the previous state and an action and uses a switch case to determine how to transition the provided State. We can take advantage of the Action Names being Strings and replace the typical switch case with a JavaScript Object that pairs our State ADT reducers with their actions.

    We can also take care of the case in which a reducer does not have an implementation for a given action, by reaching for the Maybe data type and updating our main Redux reducer to handle the case for us, by providing the previous state untouched. And all of this can be captured in a simple helper function we can use in all of our reducer files.



    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson




    Instructor: In our index file we have the select card action creator as well as our main Redux reducer, both imported from our reducers folder. We've also defined some state that contains a short list of cards and a couple of integers for tracking the moves a player has left and the moves a player has already made.

    We called the reducer, providing it both the state and the result of calling select card with the ID of the card selected. Our reducer takes both some app state and an action right back to app state. It takes in our previous state and the current action and applies our action to this turn reducer.

    The turn reducer takes an action of A to either a state instance or a null value and uses the switch case to determine which transition to apply our payload to.

    As we've already seen select card, let's take a look at the show feedback action creator. We'll just pop back over to our index, replacing select card with show feedback and see that it compares the selected card from this list to the current hint.

    Updating is correct and rank accordingly. If we pass in an unknown action like this silly verb, we get our previous state echoed back to us with no modification.

    Let's look at a couple refactors we can do to clean up some of this boilerplate. Because we're switching over a string value, we can use a plain old JavaScript object to capture this pattern. We'll define a new action reducer object with our action names as keys paired with their associated state transitions, creating entries for both select card and show feedback.

    Let's comment out the old verbose implementation for reference and clean up our arrow function to return the result of an expression that uses the type to select our transition from action reducer, thus creating a compact implementation for both of these cases.

    Once we account for this null, we'll have the entire block implemented. If our action isn't present on the object, we'll return a no op by defaulting to the prototype for a JavaScript function to guarantee that this expression will always return a function ready to accept our payload.

    We've now implemented this entire block in just a single line, defining how to select and call a given action. Not only does this work with valid actions, but it also still works for invalid ones.

    We've cleaned this up considerably, but there are still a few things we can do to make this pattern more reusable. Let's focus on our state reducer saying we now get back a state instance when called with a valid action.

    This express defines a disjunction, making it easily representable with the maybe data type. Let's pop over to our helpers file and capture this in a function that we'll export, giving it the name of create reducer, taking in an action reducer as its first argument.

    We'll define this new helper function as a function that will take this action reducer type, which is defined as an object of functions that take any type A to a state app state of unit.

    When given an action reducer, create reducer will give back what we define as a reducer, which in our case is a function taking any action of type A to a maybe of state app state of unit.

    To satisfy this reducer type, we'll need to return an action accepting function, plucking both type and payload off of a given action. For the first portion of our disjunction, we'd like to use a maybe to return our state transition if present.

    Otherwise we'd like it to give back a nothing. It just so happens we can accomplish this with a crocks prop function, which will take our type as the key to look up on our action reducer.

    To see what we've got so far, we'll jump into our turn reducer and import it in from our helpers file and then take a mighty leap downstairs to comment out our first attempt. Replacing reducer with the result of create reducer with our previously defined action reducer, which we see gives back a function wrapped in a just.

    Specifically this feedback function, which is patiently waiting to be fed the payload from our action like we had before.

    Back in our helpers file we'll map the crocks apply to combiner to apply the payload to the underlying function, placing our state instance in the maybe. Believe it or not, we're actually done, so we'll remove our old crusty reducer and add a siggy for our new hotness, which is just our reducer type.

    Now if we provide an action not covered by the reducer, we'll get back a nothing. Otherwise we'll get back our just with our new state transition. We're not quite finished. Over in our main reducer, we're not set up to deal with the maybe return by our turn reducer, so let's change focus to our main reducer and get it to work with this brand new maybe type.

    We'll provide the state to the first argument and swap out our reducer, so we're not implementing this blind. We'll clean up our arrow function, then comment out the old school and return the result of calling turn with the action.

    Next up, we need to handle this check to see if we have a state instance in our result, which we'll do by chaining in the crock safe function, passing in a predicate that checks if a given value is a state instance, taking care of the first part of our old implementation.

    If we have a state instance, we need to call this exec with function, passing in our state, which we'll do by mapping to this point free version provided by crocks to find our transition state wrapped in a maybe.

    Now if we swap out select card and reduce with our silly verb action, we see we get back a nothing, signaling that we need to echo back our previous state, which we do by using it to option our maybe to get our expected results. Using option also unwraps our valid actions as we see with select card and also with the valid show feedback.