React bindings for Vuex
inspired by react-redux
project.
react-vuex requires React 16.0+, Vue 2.0+ and Vuex 3.0+
npm install --save react-vuex
This assumes that you’re using npm package manager with a module bundler like Webpack or Browserify to consume CommonJS modules.
To look at some example projects, take a look at the examples section of this repo.
-
configure your store with state, getters, mutations and actions, according to Vuex documentation
/* * actions.js */ export const INCREMENT_ASYNC = 'INCREMENT_ASYNC'; export default { incrementAsync: (value = 1) => ({ type: INCREMENT_ASYNC, value, }), }; /* * mutations.js */ export const INCREMENT = 'INCREMENT'; export const INCREMENT_START = 'INCREMENT_START'; export const INCREMENT_STOP = 'INCREMENT_STOP'; export default { increment: (value = 1) => ({ type: INCREMENT, value, }), }; /* * store.js */ import Vue from 'vue'; import Vuex from 'vuex'; import { INCREMENT, INCREMENT_START, INCREMENT_STOP } from './mutations'; import { INCREMENT_ASYNC } from './actions'; Vue.use(Vuex); export default new Vuex.Store({ state: { count: 0, isIncrementing: false, }, getters: { countGreaterThan2: (state, getters) => state.count > 2, }, mutations: { [INCREMENT](state) { state.count += 1; }, [INCREMENT_START](state) { state.isIncrementing = true; }, [INCREMENT_STOP](state) { state.isIncrementing = false; }, }, actions: { [INCREMENT_ASYNC]({ commit, state }, payload) { commit(INCREMENT_START); return new Promise((resolve) => { setTimeout(() => { commit(INCREMENT); resolve(); }, 500); }).then(() => commit(INCREMENT_STOP)) .then(() => state.count); }, }, });
-
use
Provider
in your appThis will pass the store to all subcomponents of the app
/* * index.js */ import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-vuex'; import App from './components/App'; import store from './store'; render( <Provider store={store}> <App /> </Provider>, document.getElementById('root'), );
-
create your container component mapping state, dispatch, commit and getter to the store
/* * containers/MyContainer.js */ import { connect } from 'react-vuex'; import MyComponent from '../components/MyComponent'; import mutations from '../mutations'; import actions from '../actions'; const mapStateToProps = (state, ownProps) => ({ myCount: state.count, }); const mapDispatchToProps = (dispatch, ownProps) => ({ onIncrementAsync: val => dispatch(actions.incrementAsync(val)), }); const mapCommitToProps = (commit, ownProps) => ({ onIncrement: () => commit(mutations.increment()), }); const mapGetterToProps = (getter, ownProps) => ({ isGreaterThan2: getter.countGreaterThan2, }); const MyContainer = connect( mapStateToProps, mapDispatchToProps, mapCommitToProps, mapGetterToProps, )(MyComponent); export default MyContainer;
-
create your presentational component using mapped props
/* * components/MyComponent.js */ import React from 'react'; import PropTypes from 'prop-types'; export default class MyComponent extends React.PureComponent { constructor(props, context) { super(props, context); this.handleInc = this.handleInc.bind(this); this.handleIncAsync = this.handleIncAsync.bind(this); } handleInc() { if (this.props.onIncrement) { this.props.onIncrement(); } } handleIncAsync() { if (this.props.onIncrementAsync) { this.props.onIncrementAsync().then(() => {})); } } render() { return ( <div> Count is {this.props.myCount !== undefined && `${this.props.myCount}, `} greater than 2: {this.props.isGreaterThan2 ? 'yes' : 'no'} {this.props.onIncrement && <button onClick={this.handleInc}>Increment Sync</button> } {this.props.onIncrementAsync && <button onClick={this.handleIncAsync}>Increment Async</button> } </div> ); } } MyComponent.defaultProps = { children: undefined, isGreaterThan2: false, myCount: 0, onIncrement: undefined, onIncrementAsync: undefined, }; MyComponent.propTypes = { children: PropTypes.node, isGreaterThan2: PropTypes.bool, myCount: PropTypes.number, onIncrement: PropTypes.func, onIncrementAsync: PropTypes.func, };
-
use your container component in app
import React from 'react'; import MyContainer from '../containers/MyContainer'; export default class App extends React.Component { constructor(props, context) { super(props, context); this.state = { testValue: 123, }; } render() { return ( <div> <MyContainer /> </div> ); } }
MIT
Hey dude! Help me out for a couple of 🍻!