react-xstore

2.1.0 • Public • Published

React xStore

NPM version Downloads Build Status JavaScript Style Guide License

Simple yet powerful global state management for React, Inspired by Vuex, Redux and react-global-store, Support's Async mutations by (Actions), see examples for more informations.

NPM

Installation

npm install --save react-xstore

Usage

Wrap your components with Connect and the store will be available as store in props this.props.store.myStore then you can access store api from any component you wrap with.

  • access store let mys = this.props.store.myStore.
  • get current store state mys.state.variable.
  • call mutations mys.commit('mutation', ...params).
  • call actions for async code mys.dispatch('action', ...params).
  • manual state mutation mys.setState({variable: 'hello'}).
  • combine states or shrink object by computed property mys.computed.variables.
  • magic state getter mys.variable.
  • magically update state value by proxy mys.variable = 'hello'.
  • link store with your component, you can add stores as second parameter or leave it blank to init all stores to the component Connect(Component, ['store1', 'store2']).

and you can access the stores externally by import {External as xStore} from 'react-xstore'; then fetch store like xStore.myStore and now you have all internal methods and states available, you can commit, dispatch, setStore or update state magically.

Example 1 - simple counter

Init Store, you should import it at the main app loader

    import {Store} from 'react-xstore';
 
    new Store ({
      name: 'myStore',
      state: { // default state for current store
        counter: 25,
      },
      mutations: { // called by commit() function
        plus (append) {
          this.counter = this.counter ? this.counter + append : 60;
        },
      },
      actions: {
        plusAsync (append) { // called by dispatch() function
          setTimeout (() => {
            this.commit ('plus', append);
          }, 500);
        },
      },
      computed: {
        x5 () {
          return this.counter * 5;
        },
      },
    });

access store from any component like this

    import React, {Component} from 'react';
    import {Connect} from 'react-xstore';
 
    class First extends Component {
      render () {
        const {state, computed, setState, commit, dispatch} = this.props.store.myStore;
        return (
          <div>
            Counter is {state.counter} and x5 is {computed.x5}<br />
            <button
              onClick={() => {
                setState ({
                  counter: state.counter ? state.counter + 1 : 1,
                });
              }}
            >
              setState +1
            </button>
            <button onClick={() => commit ('plus', 50)}>
              Commit +50
            </button>
            <button onClick={() => dispatch ('plusAsync', 100)}>
              Dispatch Async +100
            </button>
          </div>
        );
      }
    }
 
    export default Connect (First, ['myStore']); // access wanted stores only, for better performance

Example 2 - advance auth manager

Init Store, and import it at the main app loader

    import {Store} from 'react-xstore';
 
    const LOGIN = 'LOGIN';
    const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
    const LOGOUT = 'LOGOUT';
 
    new Store ({
      name: 'auth',
      state: {
        isLoggedIn: !!localStorage.getItem ('token'),
      },
      mutations: {
        [LOGIN] () {
          this.pending = true;
        },
        [LOGIN_SUCCESS] () {
          this.isLoggedIn = true;
          this.pending = false;
        },
        [LOGOUT] () {
          this.isLoggedIn = false;
        },
      },
      actions: {
        login (creds) {
          this.commit (LOGIN);
          return new Promise (resolve => {
            setTimeout (() => {
              localStorage.setItem ('token', 'JWT');
              this.commit (LOGIN_SUCCESS);
              resolve ();
            }, 1000);
          });
        },
        logout () {
          localStorage.removeItem ('token');
          this.commit (LOGOUT);
        },
      },
    });

component example usage

    import React, {Component} from 'react';
    import {Connect} from 'react-xstore';
 
    class Login extends Component {
      render () {
        const {state, dispatch} = this.props.store.auth;
        return (
          <div>
            {state.isLoggedIn
              ? <span>Logged</span>
              : <span>You Need to Login</span>}
            {state.pending && <span>...</span>}
 
            <br />
            {!state.isLoggedIn &&
              <button onClick={() => dispatch ('login', {user: 'name'})}>
                Login
              </button>}
            {state.isLoggedIn &&
              <button onClick={() => dispatch ('logout')}>
                Logout
              </button>}
          </div>
        );
      }
    }
 
    export default Connect (Login); // access all stores

update store by magic setter

      let auth = this.props.store.auth;
      auth.username = 'Tamer Zorba';

Contributing

Thank you for considering contributing! Fork the repo then after you complete your awesome feature, make a pull request and we will be glad to accept after test.

License

This code is open-sourced software licensed under the MIT license

Package Sidebar

Install

npm i react-xstore

Weekly Downloads

10

Version

2.1.0

License

MIT

Last publish

Collaborators

  • tamerzorba