https://github.com/vshushkov/redux-models
Models layer for your Redux application
https://github.com/vshushkov/redux-models
graphql models react redux redux-models rest-api
Last synced: 5 months ago
JSON representation
Models layer for your Redux application
- Host: GitHub
- URL: https://github.com/vshushkov/redux-models
- Owner: vshushkov
- License: mit
- Created: 2016-12-04T14:02:04.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2023-01-03T15:15:18.000Z (over 3 years ago)
- Last Synced: 2025-12-15T20:24:54.494Z (6 months ago)
- Topics: graphql, models, react, redux, redux-models, rest-api
- Language: JavaScript
- Size: 1.44 MB
- Stars: 1
- Watchers: 2
- Forks: 1
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Redux models
[](https://travis-ci.org/vshushkov/redux-models)
[](https://codeclimate.com/github/vshushkov/redux-models/coverage)
Models layer for Redux. `redux-models` simplifies working with remote data (well.. not only remote) and helps to organize your code.
## Installation
```bash
npm install --save redux redux-models
```
## Usage
##### `models/User.js`
```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`
```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`
```jsx harmony
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
Loading...;
}
return
;
}
}
export default connect(
(state, { username }) => ({
user: User(state).findByUsername(username)
}),
(dispatch, { username }) => ({
fetchUser: () => dispatch(User.findByUsername(username))
})
)(UserAvatar);
```
[Live demo](https://codesandbox.io/s/redux-models-example-j74p7)
## API
### `createModel(options)`
#### Arguments
`options`:
- `options.name`: (`String`): Name of a model
- `options.mixins`: (`Array`): Array of mixins
- `options.methods`: (`Object`): Model's methods
- `options.reducer`: (`Function` [optional]): [Model reducer](#model-reducer).
- `options.typePrefix`: (`String` [optional]): Prefix of actions types. Default `@@redux-models`.
- `options.modelState`: (`Function` [optional]): Function to map state to model state. Default `state => 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](https://redux.js.org/basics/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:
```json5
{
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
```js
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:
```jsx harmony
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`](https://www.npmjs.com/package/redux-models-mixin-crud)
adds methods: `create`, `updateById`, `deleteById`, `find`, `findById`.
##### `crud.js`
```jsx harmony
import createMixin from 'redux-models-mixin-crud';
export default function crudMixin(path) {
return createMixin({
methods: {
create() { /*...*/ },
updateById() { /*...*/ },
deleteById() { /*...*/ },
find() { /*...*/ },
findById() { /*...*/ }
}
});
}
```
##### `book.js`
```jsx harmony
import { createModel } from 'redux-models';
import crudMixin from './crud';
export default createModel({
name: 'Book',
mixins: [crudMixin('/books')]
});
```
## Contributing
See the [Contributors Guide](https://github.com/vshushkov/redux-models/blob/master/CONTRIBUTING.md)
License
[MIT](https://github.com/vshushkov/redux-models/blob/master/LICENSE)