redux-models-creator v1.1.0-1
Redux models
Models layer for Redux. redux-models
simplifies working with remote data (well.. not only remote) and helps to organize your code.
Installation
npm install --save redux redux-models
Usage
models/User.js
import { createModel } from 'redux-models';
export default createModel({
name: 'User',
methods: {
findByUsername(username) {
return fetch(`https://api.github.com/users/${username}`).then(res =>
res.json()
);
}
}
});
store.js
import { combineReducers, applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import User from './models/User';
export default createStore(
combineReducers({
...User.reducers
}),
applyMiddleware(thunk)
);
app.js
import React from 'react';
import { connect } from 'react-redux';
import User from './models/User';
class UserAvatar extends React.Component {
componentDidMount() {
const { fetchUser } = this.props;
fetchUser();
}
render() {
const { user } = this.props;
if (!user) {
return <div>Loading...</div>;
}
return <img src={user.avatar_url} alt="avatar" />;
}
}
export default connect(
(state, { username }) => ({
user: User(state).findByUsername(username)
}),
(dispatch, { username }) => ({
fetchUser: () => dispatch(User.findByUsername(username))
})
)(UserAvatar);
API
createModel(options)
Arguments
options
:
options.name
: (String
): Name of a modeloptions.mixins
: (Array
): Array of mixinsoptions.methods
: (Object
): Model's methodsoptions.reducer
: (Function
optional): Model reducer.options.typePrefix
: (String
optional): Prefix of actions types. Default@@redux-models
.options.modelState
: (Function
optional): Function to map state to model state. Defaultstate => state[{ model name }]
.
Returns
Newly created model with defined methods. Each model method creates action to dispatch.
Model reducer
Additional data processing from the methods can be done in the model reducer.
Model reducer arguments are same as redux reducers, except the last argument types
.
It contains all action types strings your model can dispatch (including mixins action types).
In following example model User
has one method find
and it can dispatch actions with types: @@redux-models/USER/FIND
, @@redux-models/USER/FIND_SUCCESS
, @@redux-models/USER/FIND_ERROR
, @@redux-models/USER/FIND_RESET
,
so types
contains object:
{
FIND: '@@redux-models/USER/FIND',
find: '@@redux-models/USER/FIND',
FIND_SUCCESS: '@@redux-models/USER/FIND_SUCCESS',
findSuccess: '@@redux-models/USER/FIND_SUCCESS',
FIND_ERROR: '@@redux-models/USER/FIND_ERROR',
findError: '@@redux-models/USER/FIND_ERROR',
FIND_RESET: '@@redux-models/USER/FIND_RESET',
findReset: '@@redux-models/USER/FIND_RESET'
}
After processing, the data will be available in state.{ model name }.model
.
Example
import { createModel } from 'redux-models';
const defaultState = {
byId: {}
};
export default createModel({
name: 'User',
methods: {
find(query) {
// async request
}
},
reducer(state = defaultState, action, { findSuccess }) {
const { type, payload: { result } = {} } = action;
if (type === findSuccess) {
return {
...state,
byId: {
...state.byId,
...(result || []).reduce(
(byId, user) => ({
...byId,
[user.id]: user
}),
{}
)
}
};
}
return state;
}
});
Then:
import { connect } from 'react-redux';
// ...
export default connect((state, { id }) => ({
user: state.User.model.byId[id]
}))(UserCard);
Mixins
Mixins allow you to add method sets to multiple models. For example mixin
crud
adds methods: create
, updateById
, deleteById
, find
, findById
.
crud.js
import createMixin from 'redux-models-mixin-crud';
export default function crudMixin(path) {
return createMixin({
methods: {
create() { /*...*/ },
updateById() { /*...*/ },
deleteById() { /*...*/ },
find() { /*...*/ },
findById() { /*...*/ }
}
});
}
book.js
import { createModel } from 'redux-models';
import crudMixin from './crud';
export default createModel({
name: 'Book',
mixins: [crudMixin('/books')]
});
Contributing
See the Contributors Guide
License MIT