Skip to main content

Redux implementation for Python

Project description

ReduxPY

Implementation of a Redux store with support for adding feature modules, dynamically. The store exposes a reactive API based on RxPY.

What is Redux and Why

Complex applications - client or server - often need to maintain state and the more complex the application becomes the harder it is to keep track of that state. The Redux pattern addresses the management of complex state by following the ideas of Flux, CQRS, and Event Sourcing.

The basic principle boils down to:

  • Single source of truth: The state of your whole application is stored in an object tree within a single store.
  • State is read-only: The only way to change the state is to emit an action, an object describing what happened.
  • Changes are made with pure functions: To specify how the state tree is transformed by actions, you write pure reducers.

The State Tree

All state is kept in a single, read-only dictionary of type ReaduxRootState. This state is maintained and managed by the ReduxRootStore object that can be created using the create_store() method. The store allows to dispatch actions, listen for state changes and add new features.

Actions

State cannot be changed but we can create new state based on existing state and an action. The action describes how the current state will be transformed.

All state transforms are synchronous operations and will be executed by a reducer.

Reducers

Reducers are pure functions that transform a current state object into a new state object given an action.

Epics

It is a basic redux principle that all operations that compute new state are executed by synchronous reducers. In order to implement asynchronous operations we introduce the concept of Epics. An epic transforms an action into another action or set of actions and this transform may be executed asynchronously. The resulting actions could in turn give rise to new actions via an epic or they could be interpreted by a reducer.

We represent an epic as a reactive operator that transforms an action input sequence (and optionally also a state sequence) into an action otput sequence.

Feature Module

There should only be one single redux store instance per application. In traditional redux this means that the set of reducers and epics must be known at instantiation time of the store. This makes it hard to compose the overall application from a set of reusable modules.

We introduce the concept of a feature module, motivated by dynamic modules and feature store.

A feature module defines a unique identifier and optionally a reducer, epic and dependencies. The identifier is used to scope state in a top level dictionary and it is possible to add a new feature module to an existing store at any point in time.

Providing a feature module

Create and export an instance of ReduxFeatureModule for your module. The module definition consists of:

  • a unique module identifier. This identifier is also used as a namespace in the redux state
  • an optional reducer that operates on that namespace
  • an optional epic to handle asynchronous actions
  • an optional list of other feature modules this module depends on

Example

from redux import create_feature_module, ReduxFeatureModule

sample_feature_module: ReduxFeatureModule = create_feature_module(
    'SAMPLE_FEATURE', sample_reducer, sample_epic, [dep1, dep2]
)

Registering a feature module

Register the feature module with the root store using the add_feature_module method. This will also register all dependent modules in topology order.

from redux import create_store, ReduxRootStore

store: ReduxRootStore = create_store()
store.add_feature_module(sampleFeature)

Consuming a feature module

Use the select_feature method to create a selector for the desired feature.

Example

from redux import select_feature

select_sample = select_feature(sample_feature)

Side effects in Feature Modules

Feature modules may provide side effects, aka epics, for asynchronous processing. Sometimes such epics require an initialization event to execute bootstrapping logic. The store sends an initialization event for this purpose, after a feature module has been initialized. Use the of_init_feature method to subscribe to this event.

Example

from redux import of_init_feature, Epic
from rx.operators import map

initEpic: Epic = lambda actions_, state_: actions_.pipe(of_init_feature(sample_feature), map(...))

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

redux-py-0.1.1.tar.gz (12.9 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page