1.0.2 • Published 8 years ago

verysimpleredux v1.0.2

Weekly downloads
2
License
ISC
Repository
github
Last release
8 years ago

A simple Redux implementation

Build Status

This is a very simple implementation of Redux that only does the core business of Redux. It is small and easy to understand.

You can use it with require or by simply adding the verysimpleredux.js script (in that case a global VerySimpleRedux variable is created).

var redux = require("verysimpleredux");

function reducer(state, type, payload) {
  switch (type) {
    case 'INCREMENT':
      return Object.assign({}, state,
        {count : state.count + (payload.value || 1)});
    case 'DECREMENT':
      return Object.assign({}, state,
        {count : state.count - (payload.value || 1)});
  }
  return state;
}

var defaultState = {count : 0};

var store = redux.createStore(reducer, defaultState);

store.subscribe(function() {
  console.log(store.getState());
});

store.dispatch('INCREMENT');
store.dispatch('INCREMENT', {value : 10});
store.dispatch('DECREMENT', {value : 2});

To use this with a React application, I usually follow this path: 1) Create the reducer and store (see above) 2) Subscribe to the store in the componentWillMount hook and set the state in the callback 3) Return the state of the store with store.getState() in the getInitialState hook 4) Call the store's dispatch method when you want to change the state, this will eventually rerender your component 5) Handover the store to the main React component as a prop

var App = React.createClass({
  componentWillMount : function() {
    var me = this;
    this.props.store.subscribe(function() {
      me.setState(me.props.store.getState());
    });
  },
  getInitialState : function() {
    return this.props.store.getState();
  },
  onIncrement : function() {
    this.props.store.dispatch("INCREMENT");
  },
  onDecrement : function() {
    this.props.store.dispatch("DECREMENT");
  },
  render : function() {
    return (
      <div>
        <div>{this.state.count}</div>
        <button onClick={this.onIncrement}>+</button>
        <button onClick={this.onDecrement}>-</button>
      </div>
    );
  }
});

ReactDOM.render(<App store={store} />,
  document.getElementById("app"));

Asynchronous actions

To make asynchronous actions with with redux, just split them into 2 actions: 1) the request and 2) the result. For example if you want to get all the items with an AJAX request (in this example I left out some things like not mutating the state):

function reducer(state, type, payload) {
  var me = this;
  switch (type) {
    case "REQUEST_GET_ITEMS":
      api.fetch("/items").then(function(item) {
        me.dispatch("GET_ITEMS", {
          value : items
        });
      });
      return state;
    case "GET_ITEMS":
      state.items = payload.value;
      return state;
  }
}

Prevent other actions while doing an asynchronous action

A common requirement is to prevent other actions from running while doing a asynchronous action. For example if you do a POST to upload data to your server, you don't want the user to click the upload button again and again, resulting in duplicate entries in your backend. A simple solution is to add a inRequest and inRequestLock properties to the state.

var defaultState = {
  inRequest : false,
  inRequestLock : false,
  name : "Michiel van Eerd",
  age : 41
};

function reducer(state, type, payload) {

  if (state.inRequest) {
    return state;
  }

  state.inRequest = true;

  switch (type) {
    case "HAVE_BIRTHDAY":
      state = Object.assign({}, state, {age : state.age + 1});
      break;
    case "HAVE_BIRTHDAY_REQUEST":
      state.inRequestLock = true;
      setTimeout(function() {
        state.inRequestLock = false;
        state.inRequest = false;
        store.dispatch("HAVE_BIRTHDAY");
      }, 2000);
      break;
    case "CHANGE_NAME":
      state = Object.assign({}, state, {name : payload.value || "Pete"});
      break;
  }

  if (!state.inRequestLock) {
    state.inRequest = false;
  }

  return state;
}

var store = VerySimpleRedux.createStore(reducer, defaultState);

var App = React.createClass({
  getInitialState : function() {
    return this.props.store.getState();
  },
  componentWillMount : function() {
    var me = this;
    this.props.store.subscribe(function() {
      me.setState(me.props.store.getState());
    });
  },
  render : function() {
    var loader = this.state.inRequest
      ? (<div id="loader">Loading...</div>) : null;
    return (
      <div>
        <p>Ik ben {this.state.name} en ben {this.state.age} jaar oud!</p>
        {loader}
      </div>
    );
  }
});

ReactDOM.render(<App store={store} />, document.getElementById("app"));

setTimeout(function() {
  store.dispatch("HAVE_BIRTHDAY_REQUEST");
  store.dispatch("CHANGE_NAME", {
    value : "Jantje"
  });
}, 1000);
1.0.2

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago