All Projects → shakacode → redux-interactions

shakacode / redux-interactions

Licence: other
Composing UI as a set of interactions

Projects that are alternatives of or similar to redux-interactions

redux-leaves
Write once. Reduce anywhere.
Stars: ✭ 52 (+136.36%)
Mutual labels:  state-management, reducer
RxReduxK
Micro-framework for Redux implemented in Kotlin
Stars: ✭ 65 (+195.45%)
Mutual labels:  state-management, reducer
flow-state
UI state management with RxJS.
Stars: ✭ 33 (+50%)
Mutual labels:  state-management, reducer
react-stateful-component
Functional stateful React components with sideEffect support
Stars: ✭ 19 (-13.64%)
Mutual labels:  state-management, reducer
Redux Machine
A tiny library (12 lines) for creating state machines in Redux apps
Stars: ✭ 338 (+1436.36%)
Mutual labels:  state-management, reducer
Juicr.js
A simple (and tiny <1kb) redux inspired reducer for handling state changes.
Stars: ✭ 102 (+363.64%)
Mutual labels:  state-management, reducer
riduce
Get rid of your reducer boilerplate! Zero hassle state management that's typed, flexible and scalable.
Stars: ✭ 14 (-36.36%)
Mutual labels:  state-management, reducer
React Recomponent
🥫 Reason-style reducer components for React using ES6 classes.
Stars: ✭ 272 (+1136.36%)
Mutual labels:  state-management, reducer
Redux Orm
A small, simple and immutable ORM to manage relational data in your Redux store.
Stars: ✭ 2,922 (+13181.82%)
Mutual labels:  state-management, reducer
Use Substate
🍙 Lightweight (<600B minified + gzipped) React Hook to subscribe to a subset of your single app state.
Stars: ✭ 97 (+340.91%)
Mutual labels:  state-management, reducer
Redhooks
Predictable state container for React apps written using Hooks
Stars: ✭ 149 (+577.27%)
Mutual labels:  state-management, reducer
UniTEA
Implementation of The Elm Architecture for Unity3D
Stars: ✭ 31 (+40.91%)
Mutual labels:  state-management
mst-effect
💫 Designed to be used with MobX-State-Tree to create asynchronous actions using RxJS.
Stars: ✭ 19 (-13.64%)
Mutual labels:  state-management
ngx-redux-core
The modern redux integration for Angular 6+
Stars: ✭ 32 (+45.45%)
Mutual labels:  reducer
atomic-state
Atomic State is a state management library for React
Stars: ✭ 15 (-31.82%)
Mutual labels:  state-management
unstated
Simple state management for react
Stars: ✭ 12 (-45.45%)
Mutual labels:  state-management
hoox
Functional react state management base on hooks
Stars: ✭ 80 (+263.64%)
Mutual labels:  state-management
gstate
A crazy state management for lazy programmers
Stars: ✭ 27 (+22.73%)
Mutual labels:  state-management
storken
🦩 Storken is a React State Manager. Simple as `useState`.
Stars: ✭ 22 (+0%)
Mutual labels:  state-management
quick-redux
helper functions to make redux and react development quicker
Stars: ✭ 61 (+177.27%)
Mutual labels:  state-management

redux-interactions

Thinking of UI in terms of interactions makes life easier.

What and Why

This is not a library, but a pattern.

There are two ways of thinking of about UI: in terms of state or in terms of interactions.

State-based model

This pattern is common in the Redux community. In this style of thinking, the building blocks of the app are reducers. Each reducer is tightly coupled to a specific part of the state. It decides how to respond to actions from the outside. It has full control over its part of the state, and that’s its only concern.

The main take away here is that state is smart.

Interactions-based model

In this model, application state is represented as an inert tree.

Check out redux-tree as it's a big part of interactions pattern.

When a user interacts with the UI, the application changes its state in response. As opposed to a reducers-based model, state is a passive data container here. And interactions are the ones in charge.

state:
  entities:
    posts: { index, entities }
    comments: { entities }
  ui:
    postsList: { processingPosts }
    ...

State tree

Let’s say a user manages his posts and removes one of them by clicking the “Delete” button. What’s happening under the hood? The state of this UI part is stored in the state.ui.postsList leaf. Clicking on the button, a user triggers an action creator and the app starts a request to the server. In response to this action, postId is added to the processingPosts set to show the spinner in the UI. It requires a change of the single ui.postsList leaf. Let’s describe it in the interaction module:

// Action creator: returns request action
const requestAction = postId => ({
  type: 'POST_DELETE_REQUESTED',
  postId,
});

// Action handler: reduces the state of the single leaf
const onRequest = {
  POST_DELETE_REQUESTED:
    (state, { postId }) =>
      state.update('processingPosts', postIds => postIds.add(postId)),
};

When a server responds with a success:

  • postId must be removed from the processingPosts
  • post entity must be removed from the entities.posts leaf. 

This action entails changing 2 different leaves:

// Action creator: returns success action
const successAction = postId => ({
  type: 'POST_DELETE_SUCCEEDED',
  postId,
});

// Action handlers: passing array of the reducers for this action type
//                  to apply sequence of the changes to the state tree
const onSuccess = {
  POST_DELETE_SUCCEEDED: [
    // 1. hide spinner
    (state, { postId }) =>
      state.update('processingPosts', postIds => postIds.delete(postId)),

    // 2. remove post entity
    {
      leaf: ['entities', 'posts'], // <= keypath to the leaf of the state
      reduce:
        (postsEntitiesState, { postId }) =>
          postsEntitiesState
            .updateIn(['index'], index => index.delete(postId))
            .updateIn(['entities'], entities => entities.delete(postId)),
    },
  ],
};

Notice how easy it is to follow what’s going on here because the logic of a single interaction is contained entirely in a single module. Try it and you will see how easy it is writing code like this.

The key point is that an interaction decides which part(s) of the state will be updated in response to the action.

Files structure

This approach proposes to represent interactions as a modules.

|- components/            # representation
  |-- index.js
  |-- index.css
|- interactions/          # modules w/ interactions
  |-- postEdit.js
  |-- postDelete.js
|- selectors/             # data selectors
  |-- ...
|- index.js               # container w/ `connect`
|- actions.js             # list of action creators
|- leaf.js                # leaf creator (see redux-tree)
|- state.js               # state definition

Everything about the interaction is declared in the interaction module. Once interaction is written, connect it to the store using redux-tree and you're all set.

Main wins here:

  • Changing things is easy
    All the changes in the app caused by the interaction are gathered in one place that’s easy to find, easy to reason about, and easy to change, move or remove. In each case, you’re dealing with files and folders dedicated to a given interaction instead of chunks of code scattered around disparate actions and reducer modules.
  • Better focus
    When you’re working on an interaction, you’re focused only on code related to an interaction. There aren’t any distractions from unrelated code.
  • Stronger typings
    With redux-tree you get 1-to-1 mapping between action creator and action handler. It means you can strictly type an action that you dispatch via AC and this is exactly what you receive in AH. See flow example.

Examples

  • basic-interactions [ live · source ]
    Simple counter reimplemented with interactions.
  • async-interactions [ live · source ]
    The real world app example.
  • flow-interactions [ live · source ]
    Redux app typed w/ flow.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].