nanxiaobei / Retalk
Programming Languages
Projects that are alternatives of or similar to Retalk

The simplest solution for Redux.
English | 简体中文
Why
- Simplest Redux - Same syntax as React components.
-
Only 2 APIs -
setStore()
andwithStore()
. - Async models - Fully code splitting support for models.
- Auto loading - Auto loading state for async actions.
Install
yarn add retalk
# or
npm install retalk
Usage
1. Model
Usually we'll set several routes in our app, one route with one model, so we'll have several models.
Write the model like a React component, just without the lifecycle methods.
class CounterModel {
state = {
count: 0,
};
add() {
// this.state -> Get state of own model
// this.setState() -> Set state of own model
// this.someAction() -> Call actions of own model
// this.models.someModel.state -> Get state of other models
// this.models.someModel.someAction() -> Call actions of other models
const { count } = this.state;
this.setState({ count: count + 1 });
}
async addLater() {
// Auto `someAsyncAction.loading` state can be use
await new Promise((resolve) => setTimeout(resolve, 1000));
this.add();
}
}
2. Store
Use setStore()
to set up all models with theirs namespaces.
import { setStore } from 'retalk';
const store = setStore({
counter: CounterModel,
// Other models...
});
3. View
Use withStore()
to connect models and components.
import React from 'react';
import { withStore } from 'retalk';
const Counter = ({ count, add, addLater }) => (
<div>
<p>{count}</p>
<button onClick={add}>+</button>
<button onClick={addLater}>+ ⏳{addLater.loading && '...'}</button>
</div>
);
const CounterWrapper = withStore({
counter: ['count', 'add', 'addLater'],
})(Counter);
4. App
Use <Provider>
to provide the store to your app.
import ReactDOM from 'react-dom';
import { Provider } from 'retalk';
const App = () => (
<Provider store={store}>
<CounterWrapper />
</Provider>
);
ReactDOM.render(<App />, document.getElementById('root'));
Demo
API
1. setStore()
const store = setStore(models, middleware);
Pass models
and middleware
(both are optional), Setup the one and only store.
In development
mode, Redux DevTools will be enabled by default, make sure its version >= v2.15.3 and not v2.16.0.
const store = setStore(
{
home: HomeModel,
counter: CounterModel,
},
[logger, crashReporter]
);
2. withStore()
withStore(...modelNames)(Component)
Eject one or more models' state and actions to a component's props.
There are 3 ways to use it:
Use string to eject all
const CounterWrapper = withStore('home', 'counter')(Counter);
The Simplest way, but if some unused props are injected, it will also trigger a re-render.
This method can be used if determined that all injected props will be used, or to rapid develop.
Use object to customize
const CounterWrapper = withStore({
home: ['name', 'setName'],
counter: ['count', 'add', 'addLater'],
})(Counter);
Customize the injected props, only inject the needed props, so to optimize the performance.
mapStateToProps()
... to customize more
Use const CounterWrapper = withStore(mapStateToProps, mapDispatchToProps)(Counter);
For more customization of the injected props, you can use mapStateToProps
, mapDispatchToProps
etc.
At that time, withStore()
will be used as connect()
.
3. Provider & batch()
Just redux-redux
's Provider
and batch()
.
You can import them from retalk
to simplify development.
FAQ
Async import models?
Setup the store with setStore()
, then use libs like loadable-components
to import components and models.
Then, use store.add()
to eject models to store.
Here is an example with loadable-components
:
import React from 'react';
import loadable from 'loadable-components';
const AsyncCounter = loadable(async () => {
const [{ default: Counter }, { default: CounterModel }] = await Promise.all([
import('./Counter/index.jsx'),
import('./Counter/Model.js'),
]);
store.add({ counter: CounterModel }); // Use `store.add(models)`, like `setStore(models)`
return (props) => <Counter {...props} />;
});