Gathering detailed insights and metrics for redux-store-generator
Gathering detailed insights and metrics for redux-store-generator
Gathering detailed insights and metrics for redux-store-generator
Gathering detailed insights and metrics for redux-store-generator
redux-shapeshifter-middleware
Redux middleware for empowering your actions using `axios` and `qs` libraries combined.
redux-generator-cli
Boilerplate for redux with redux toolkit
redux-store-codegen
An easy code generator to auto generate actions, thunk-action-creators, reducers and selectors from a simple store schema definition
generator-context-store
scaffold a redux like store with context api
npm install redux-store-generator
Typescript
Module System
Node Version
NPM Version
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
Redux-store-generator turns a JSON structure into a fully-fledged redux store.
Redux-store-generator
generates:
Strongly-typed
actions to mutate the stateThe actions follow simple REST-like verbs (patch, update, delete, etc). The benefits of this approach are:
1yarn add redux-store-generator
1import { 2 generateReducersForStore, 3 generateActionsForStore, 4} from 'redux-store-generator'; 5 6type IUser = { 7 name: string; 8 email: string; 9}; 10 11type MyStore = { 12 user: IUser; 13}; 14 15const schema: MyStore = { 16 user: { 17 name: 'Michael', 18 email: 'michael.m@example.com', 19 }, 20}; 21 22const rootReducer = generateReducersForStore<MyStore>(schema); 23const actions = generateActionsForStore<MyStore>(schema); 24 25const store = createStore(combineReducers(rootReducer)); 26 27// Now you have a redux-store which responds to the auto-generated actions 28// In this example, this actions can be dispatch on the store: 29actions.user.patch({ email: 'michael@other-domain.com' }); 30actions.user.setAll({ name: 'Pia', email: 'pia@domain.com' });
Redux-store-generator
depends on specific conventions:
* all inner items are expected to have an "id" field of type string
To cover most data-structure needs, there are 4 types of entity structures:
Type | Description | Example |
---|---|---|
Single | A simple key-value object | currentUser |
Collection | For instance: Record<id, Product>* | Products |
List | For instance: Log[] | Logs |
GroupedList | For instance: Record<id, Chat> ** | Chats |
* id represents a string
** In this example Chat would have an "items" field which contains an array of chat messages
1import { 2 generateReducersForStore, 3 generateActionsForStore, 4} from 'redux-store-generator'; 5import { combineReducers, createStore } from 'redux'; 6 7type IUser = { 8 name: string; 9 email: string; 10}; 11 12type ILog = { 13 id: string; 14 timestamp: number; 15 message: string; 16}; 17 18type IProduct = { 19 id: string; 20 name: string; 21 price: number; 22}; 23 24type IChatMessage = { 25 id: string; 26 displayName: string; 27 timestamp: number; 28 message: string; 29 isSeen: boolean; 30}; 31 32type IChat = { 33 id: string; 34 title: string; 35 items: IChatMessage[]; 36}; 37 38type MyStore = { 39 currentUser: IUser; 40 logs: ILog[]; 41 products: Record<string, IProduct>; 42 chats: Record<string, IChat>; 43}; 44 45const schema: MyStore = { 46 currentUser: { 47 name: 'Michael', 48 email: 'michael.m@example.com', 49 }, 50 logs: [ 51 { 52 id: '1', 53 timestamp: 0, 54 message: '', 55 }, 56 ], 57 products: { 58 1: { 59 id: '1', 60 name: 'Dji Mavic air 2', 61 price: 1099, 62 }, 63 }, 64 chats: { 65 1: { 66 id: '1', 67 title: 'Sales', 68 items: [ 69 { 70 id: '1', 71 displayName: 'Laura', 72 isSeen: true, 73 message: "Yes, it's available", 74 timestamp: 0, 75 }, 76 ], 77 }, 78 }, 79}; 80 81const rootReducer = generateReducersForStore<MyStore>(schema); 82const actions = generateActionsForStore<MyStore>(schema); 83 84const store = createStore(combineReducers(rootReducer)); 85 86// Now you have a redux-store which responds to the auto-generated actions 87// this actions can be dispatch on the store: 88 89actions.currentUser.patch({ email: 'michael@other-domain.com' }); 90actions.currentUser.setAll({ name: 'Pia', email: 'pia@domain.com' }); 91 92actions.logs.push({ id: '2', message: '', timestamp: 0 }); 93actions.logs.pop(); 94actions.logs.pushMany([{ id: '2', message: '', timestamp: 0 }, { id: '3', message: '', timestamp: 0 }]); // prettier-ignore 95actions.logs.setAll([{ id: '2', message: '', timestamp: 0 }, { id: '3', message: '', timestamp: 0 }]); // prettier-ignore 96actions.logs.clear(); 97 98actions.products.add({ id: '2', name: '', price: 10 }); 99actions.products.setAll({ 2: { id: '2', name: '', price: 10 } }); // replaces the collection 100actions.products.setMany({ 2: { id: '2', name: '', price: 10 } }); // changes specific items 101actions.products.set('1', { id: '1', name: '', price: 10 }); 102actions.products.delete('1'); 103actions.products.patch('1', { name: 'New product name' }); 104 105actions.chats.add({ id: '2', title: '' }); 106actions.chats.setAll({ 2: { id: '2', title: '', items: [] } }); // replaces the collection 107actions.chats.setMany({ 2: { id: '2', title: '', items: [] } }); // changes specific items 108actions.chats.set('1', { id: '1', title: '' }); 109actions.chats.delete('1'); 110actions.chats.patch('1', { title: 'New product name' }); 111// and for the inner items 112actions.chats.pushItem('1', { id: '1', displayName: '', timestamp: 0, message: '', isSeen: false }); // prettier-ignore 113actions.chats.popItem('1'); 114actions.chats.pushManyItems('1', [{ id: '1', displayName: '', timestamp: 0, message: '', isSeen: false } ]); // prettier-ignore 115actions.chats.setItems('1', [{ id: '1', displayName: '', timestamp: 0, message: '', isSeen: false } ]); // prettier-ignore 116actions.chats.clearItems('1');
Verb | Description |
---|---|
patch | partially changes the entity |
setAll | replaces the entity |
Verb | Description |
---|---|
push | adds an item to the queue |
pop | pops an item from the queue |
pushMany | adds many items to the queue |
setAll | replaces the queue |
clear | clears the queue |
Verb | Description |
---|---|
setAll | replaces the collection |
setMany | adds many items to the collection |
set | replaces a specific item |
delete | deletes a specific item |
patch | modifies a specific item |
Note GroupedLists are a combination of a collection with an inner queue
Verb | Description |
---|---|
setAll | replaces the collection |
setMany | adds many items to the collection |
set | replaces a specific item |
delete | deletes a specific item |
patch | modifies a specific item |
pushItem | adds an item to an inner items queue * |
popItem | pops an item from an inner items queue * |
pushManyItems | adds many items to an inner items queue * |
setItems | replaces an inner items queue * |
clearItems | clears an inner items queue * |
* if you have a GroupedList of chats an one of the chat is { id: '10', title: 'Important Chat', items: [] }, the inner
items
field represents a queue of chat messages. all the verbs which manipulate the inner items queue refer to the chat messages in this example. To illustrate,pushItem
would be used when a new chat message arrives for this chat.
Helper actions are available to support API data fetches via GET and creation of new items via POST.
Entity type | Verb |
---|---|
single | get |
queue | get * |
collection | get * |
groupedList | get * |
collection | add |
groupedList | add |
* parameters can be added in a JSON structure
Those actions do not effect the store's state, they have no side-effects. They exist only to be caught via a middleware or a saga so they can be handled as needed.
For instance, when a user add a new item to a collection, an Id
is not yet available as it will be given by the backend, so a common practice would be:
add
action:
1actions.products.add({ name: 'new product', price: 10.9 }); // dispatch this action
set
action:
1// dispatch this action 2actions.products.set('540', { 3 id: '540', 4 name: 'new product', 5 price: 10.9, 6});
In this example the backend returned
540
as the newly-generated id for this product
1// for GET 2actions.currentUser.get(); 3actions.logs.get({ page: 2 }); 4actions.products.get({ search: 'drone', filter: {}, sort: {} }); 5actions.chats.get({ limit: 50 }); 6 7// for POST 8actions.products.add({ name: '', price: 10 }); 9actions.chats.add({ title: '' });
Redux Toolkit is an alternative to reduce boilerplate in redux-powered web apps. It may be better suited for certain use-cases. This comparison table may help you decide what is the best tool for your needs:
redux-store-generator | redux-toolkit | |
---|---|---|
Reducers | auto-generated | manually written * |
API | none | via RTK query |
Business logic in reducers | not supported | supported |
Redux-toolkit
(with RTK query
) aims to provide an opinionated solution for a complete data cycle, from action invocation to side-effects, back to store manipulation. It has a mechanism for contributing slices to the store which are fully-configured (with API concerns).
redux-store-generator
on the other hand, is a thinner opinionated solution for managing collections. You are required to implement an API mechanism on your own or use another package to do so.
The core question is whether you want to treat your store as a simple data-warehouse or a hub for business logic implementations.
If you wish to implement business-logic in your reducers, redux-toolkit
would be a better fit for you. If you want to keep your reducers' logic simple and use other ways (sagas, middlewares) to implement business logic, redux-store-generator
might better cater to your needs.
* simplified via convenient methods
No vulnerabilities found.
No security vulnerabilities found.