0.5.0 • Published 8 years ago

redux-nimble v0.5.0

Weekly downloads
10
License
MIT
Repository
-
Last release
8 years ago

redux-nimble

A library that removes a lot of the boilerplate necessary to use redux.

Disclaimer: I have no idea whether this is useful or dumb.

Why

Because I didn't understand why I had to write all this boilerplate especially when working with smaller projects.

The store

redux-nimble exposes a Store class, which should be used instead of Redux's createStore function.

import Store from 'redux-nimble';

const reducers = {...};
const actions = {...};
const defaultState = {...};

const store = new Store(reducers, actions, defaultState, middleware, moreMiddleware);

store.getState();

Reducers and actions

Although pretty similar, reducers and actions in redux-nimble are not identical to those in classic redux. Reducers and actions are passed into the Store wrapped in objects. Both reducers and actions will become available on the top level of the Store object, which of course means that they must have different names. In redux-nimble, reducers double as actions.

Both reducers and actions have access to the store via this. Reducers need to return the changed portion of state, where as action return values are irrelevant making them suitable for async operations.

Reducers

state is always passed to reducers as the first argument. The return value is otherwise identical to classic redux reducers, but with redux-nimble you only need to return the changed properties of the state.

// Having reducers like these:
const reducers = {
   setRoute(state, route) {
      return {currentRoute: route};
   },
   addPosts(state, posts) {
      return {posts: state.posts.concat(posts)};
   }
};

...

// ...will make them available on the store like this:
store.setRoute('home-page');
store.addPosts([...]);

Actions

Return values of actions are ignored making them ideal for async operations. Each action will have access to the store via this, which can be used to call other actions (including reducers, since reducers double as actions).

// Having actions like these:
const actions = {
   fetchMorePosts(offset) {
      return API.fetchPosts(offset)
      .then(posts => {
         this.addPosts(posts); // a reducer
      });
   },
   setCurrentRouteInTenSeconds(route) {
      setTimeout(() => this.setRoute(route), 10000);
   }
};

...

// ...will make them available on the store like this:
store.fetchMorePosts(10); // still returns a Promise
store.setCurrentRouteInTenSeconds('home-page');

Change listeners

redux-nimble provides its own subscription system where state change listeners can be attached to only certain top level properties of the state. The subscribe method takes two arguments: 1. a list of keys as an array or a single key as a string 2. the callback function that gets passed the new state

and returns a function that can be used to remove the listener.

const unsubscribe = store.subscribe('route', state => {
   console.log('Listener called!');
});
store.setRoute('home'); // Will trigger the callback.
store.addPosts([...]); // Won't trigger the callback.

unsubscribe(); // Remove the listener.

Accessing the Redux store

The Redux store can easily be accessed through the redux property:

store.redux.getState();
store.redux.subscribe(() => ...);

Usage with React

redux-nimble provides components similar to react-redux. See the example below.

import React from 'react';
import ReactDOM from 'react-dom';

import {Store, Provider, connect} from 'redux-nimble';

const defaultState = {value: 100};

// The store is bound to "this" of each action.
const actions = {
   setValueAsync(value) {
      setTimeout(() => {
         this.setValue(value);
      }, 1000);
   }
};

// Reducers only need to return the changed properties of the state.
const reducers = {
   setValue(state, value) {
      return {value};
   },
   increaseValue(state, value) {
      return {value: state.value + value};
   },
   setData(state, data) {
      return {data};
   }
};

// Initialize the store with actions, reducers and a default state.
// Reducers and actions become equal functions on the top level of the store object.
const store = new Store(reducers, actions, defaultState);



// Integration with React is much like with react-redux.
class Main extends React.Component {
   render() {
      // Wrap everything inside of a Provider-component.
      return (
         <Provider store={store}>
            <ConnectedChild />
         </Provider>
      );
   }
}

class Child extends React.Component {
   render() {
      return (
         <div>
            <p>Value: {this.props.value}, data: {this.props.data}</p>
            <button onClick={() => this.props.increaseValue(2)}>Increase value by 2</button>
            <button onClick={() => this.props.setData(this.props.value)}>Update data</button>
         </div>
      );
   }
}

// Attach state properties and store functions to properties.

// The short way:
const ConnectedChild = connect(['value', 'data'], ['increaseValue', 'setData'])(Child);
// ...or the long way:
const ConnectedChild = connect(
   state => ({
      value: state.value,
      data: state.data
   }),
   store => ({
      increaseValue: value => store.increaseValue(value),
      setData: data => store.setData(data)
   })
)(Child);

ReactDOM.render(<Main />, document.getElementById('content'));
0.5.0

8 years ago

0.4.0

8 years ago

0.3.0

8 years ago

0.2.0

8 years ago

0.1.4

8 years ago

0.1.3

8 years ago

0.1.2

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago