Reducer (revived.reducer) module documentation

This module implements helper functions and classes that can be used to define reducers in the same fashion of redux ones, but using decorators instead of anonymous functions.

Things you should never do inside a reducer:

  • Mutate its arguments;
  • Perform side effects like API calls and routing transitions;
  • Call non-pure functions.

Given the same arguments, it should calculate the next state and return it. No surprises. No side effects. No API calls. No mutations. Just a calculation.

Create a reducer

A reducer is a function that looks like this:

def dummy(prev, action):
    next = prev
    if action.type == ActionType.DUMMY_ACTION_TYPE:
        # Do something
        return next

In order to decrease the amount of required boilerplate revived makes use of a lot of python goodies, especially decorators.

While every function can be used as reducer (as long as it takes the proper parameters), the easiest way to create a reducer that handles a specific type of actions is to use the revived.reducer.reducer decorator.

@reducer(ActionType.DUMMY_ACTION_TYPE)
def dummy(prev, action):
    next = prev
    # Do something
    return next

Combine reducers

You can naively combine several reducers in this way:

def dummy(prev, action):
    next = prev
    if action.type == ActionType.DUMMY_ACTION_TYPE1:
        # Do something
        return next
    elif action.type == ActionType.DUMMY_ACTION_TYPE2:
        # Do something different
        return next
    else:
        return next

but this is going to make your reducer function huge and barely readable. revived.reducer contains utility functions that allows you to create much more readable reducers.

Reducers can (and should) be combined. You can easily do this combination using revived.reducer.combine_reducers.

The following example will produce a combined reducer where both the reducers will handle the whole subtree passed to it: exactly the same result of the previous snippet of code!

@reducer(ActionType.DUMMY_ACTION_TYPE1)
def dummy1(prev, action):
    next = prev
    # Do something
    return next

@reducer(ActionType.DUMMY_ACTION_TYPE2)
def dummy2(prev, action):
    next = prev
    # Do something
    return next

combined_reducer = combine_reducers(dummy1, dummy2)

Note: a combined reducer is a reducer and can be combined again with other reducers allowing you to creare every structure you will ever need in your app.

Pass a subtree of the state

If you want it is possible to pass to a reducer only a subtree of the state passed to the combined reducer. To do this you should use keyword arguments in this way:

@reducer(ActionType.DUMMY_ACTION_TYPE1)
def dummy1(prev, action):
    next = prev
    # Do something
    return next

@reducer(ActionType.DUMMY_ACTION_TYPE2)
def dummy2(prev, action):
    next = prev
    # Do something
    return next

combined_reducer = combine_reducers(dummy1, dummy_subtree=dummy2)

In this example dummy1 will receive the whole subtree passed to the combined_reducer while dummy2 will only receive the dummy_subtree subtree.

Create a reducer module

A reducer module is an utility object that behave exactly like a single reducer, but permits to register more reducers into it. You will use it to define a bunch of reducers that are all handling the same subtree of the state.

Note that this is only a helper construct, because the following snippet of code:

mod = Module()

@mod.reduder(ActionType.DUMMY_ACTION_TYPE1)
def dummy1(prev, action):
    next = prev
    # Do something
    return next

@mod.reduder(ActionType.DUMMY_ACTION_TYPE2)
def dummy2(prev, action):
    next = prev
    # Do something
    return next

has exactly the same result of:

@reducer(ActionType.DUMMY_ACTION_TYPE1)
def dummy1(prev, action):
    next = prev
    # Do something
    return next

@reducer(ActionType.DUMMY_ACTION_TYPE2)
def dummy2(prev, action):
    next = prev
    # Do something
    return next

module_reducer = combine_reducers(dummy1, dummy2)

And of course you can combine a reducer module with other reducers and reducer modules.

class revived.reducer.Module[source]

Helper class for module creations.

This is just an helper class: you can obtain the same result using the reducer decorator and then combining all the defined reducers as top-level reducers. The module instance will work exactly as a reducer function, but will call all the registered reducers. The call order is not guaranteed.

Return type:None
reducer(action_type)[source]

Decorator function to create a reducer.

Creates a reducer attached to the module. This reducer is handling the specified action type and it is going to be ignored in case the action is of a different type.

Parameters:action_type (ActionType) – The action type.
Return type:Callable
Returns:The reducer function.
revived.reducer.combine_reducers(*top_reducers, **reducers)[source]

Create a reducer combining the reducers passed as parameters.

It is possible to use this function to combine top-level reducers or to assign to reducers a specific subpath of the state. The result is a reducer, so it is possible to combine the resulted function with other reducers creating at-will complex reducer trees.

Parameters:
  • top_reducers (Union[Callable, Module]) – An optional list of top-level reducers.
  • reducers (Union[Callable, Module]) – An optional list of reducers that will handle a subpath.
Return type:

Callable

Returns:

The combined reducer function.

revived.reducer.reducer(action_type)[source]

Decorator function to create a reducer.

Creates a reducer. This reducer is handling the specified action type and it is going to be ignored in case the action is of a different type.

Parameters:action_type (ActionType) – The action type. :returns: The reducer function.
Return type:Callable
Returns:The reducer function.