Build Status Coverage Status Codacy Badge npm version file size file size
Rematch is Redux best practices without the boilerplate. No more action types, action creators, switch statements or thunks.
- Getting Started
- Purpose
- Examples
- Migration Guide
- API Reference
- Recipes
- Plugins
- Inspiration
npm install @rematch/core
init configures your reducers, devtools & store.
import { init } from '@rematch/core' import * as models from './models' const store = init({ models, })
For a more advanced setup, see plugins and Redux config options.
The model brings together state, reducers, async actions & action creators in one place.
export const count = { state: 0, // initial state reducers: { // handle state changes with pure functions increment(state, payload) { return state + payload } }, effects: { // handle state changes with impure functions. // use async/await for async actions async incrementAsync(payload, rootState) { await new Promise(resolve => setTimeout(resolve, 1000)) this.increment(payload) } } }
Understanding models is as simple as answering a few questions:
- What is my initial state? state
- How do I change the state? reducers
- How do I handle async actions? effects with async/await
dispatch is how we trigger reducers & effects in your models. Dispatch standardizes your actions without the need for writing action types or action creators.
import { dispatch } from '@rematch/core' // state = { count: 0 } // reducers dispatch({ type: 'count/increment', payload: 1 }) // state = { count: 1 } dispatch.count.increment(1) // state = { count: 2 } // effects dispatch({ type: 'count/incrementAsync', payload: 1 }) // state = { count: 3 } after delay dispatch.count.incrementAsync(1) // state = { count: 4 } after delay
Dispatch can be called directly, or with the dispatch[model][action](payload) shorthand.
import React from 'react' import ReactDOM from 'react-dom' import { Provider, connect } from 'react-redux' import { init } from '@rematch/core' // State const count = { state: 0, // initial state reducers: { // handle state changes with pure functions increment(state, payload) { return state + payload } }, effects: { // handle state changes with impure functions. // use async/await for async actions async incrementAsync(payload, rootState) { await new Promise(resolve => setTimeout(resolve, 1000)) this.increment(payload) } } } const store = init({ models: { count } }) // View const Count = props => ( <div> The count is {props.count} <button onClick={props.increment}>increment</button> <button onClick={props.incrementAsync}>incrementAsync</button> </div> ) const mapState = state => ({ count: state.count }) const mapDispatch = dispatch => ({ increment: () => dispatch.count.increment(1), incrementAsync: () => dispatch.count.incrementAsync(1) }) const CountContainer = connect(mapState, mapDispatch)(Count) ReactDOM.render( <Provider store={store}> <CountContainer /> </Provider>, document.getElementById('root') )
Moving from Redux to Rematch involves very few steps.
See the @rematch/core API
Like this project? ★ us on Github :)