Skip to main content

Installation

Installation is as simple as running the npm command:

bash
npm install @rematch/core
bash
npm install @rematch/core

Basic usage​

Step 1: Define models​

Model brings together state, reducers, async actions in one place. It describes a slice of your redux store and how it changes.

Understanding configuration of models is as simple as answering a few questions:

  1. What is my initial state? state
  2. How do I change the state? reducers
  3. How do I handle async actions? effects with async/await

Below we define a simple model count.

js
export const count = {
state: 0, // initial state
reducers: {
// handle state changes with pure functions
increment(state, payload) {
return state + payload;
},
},
effects: (dispatch) => ({
// handle state changes with impure functions.
// use async/await for async actions
async incrementAsync(payload, rootState) {
await new Promise((resolve) => setTimeout(resolve, 1000));
dispatch.count.increment(payload);
},
}),
};
js
export const count = {
state: 0, // initial state
reducers: {
// handle state changes with pure functions
increment(state, payload) {
return state + payload;
},
},
effects: (dispatch) => ({
// handle state changes with impure functions.
// use async/await for async actions
async incrementAsync(payload, rootState) {
await new Promise((resolve) => setTimeout(resolve, 1000));
dispatch.count.increment(payload);
},
}),
};

Step 2: Init store​

init is the only method you need to call to build a fully configured Redux store. You can visit api reference to learn more about all configuration parameters that can be used but as a bare minimum it is enough to provide models object. It should contain mapping from a model name to model definition (created in step 1).

store.js
js
import { init } from "@rematch/core";
import * as models from "./models";
const store = init({ models });
export default store;
store.js
js
import { init } from "@rematch/core";
import * as models from "./models";
const store = init({ models });
export default store;

Step 3: Dispatch actions​

With dispatch you can trigger reducers & effects in your models. Dispatch standardizes your actions without the need for writing action types or action creators. Dispatch can be called directly, just like with plain Redux, or with the dispatch[model][action](payload) shorthand.

js
const { dispatch } = store;
// 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
js
const { dispatch } = store;
// 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

Step 4: View​

Rematch can be used with native redux integrations such as "react-redux". See an example below.

App.js
js
import React from "react";
import ReactDOM from "react-dom";
import { Provider, connect } from "react-redux";
import store from "./store";
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")
);
App.js
js
import React from "react";
import ReactDOM from "react-dom";
import { Provider, connect } from "react-redux";
import store from "./store";
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")
);