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 install --save react-xstore
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.
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 performanceInit 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 storesupdate store by magic setter
let auth = this.props.store.auth;
auth.username = 'Tamer Zorba';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.
This code is open-sourced software licensed under the MIT license
