1 | Redux CRUD Manager
|
2 | ===================
|
3 |
|
4 | ## Keep your redux store sync with your server.
|
5 |
|
6 | ### Warning: this package is not yet published on npm. It is still in alpha development
|
7 |
|
8 | Redux CRUD Manager provide a simple way to sync your redux store with your remote server.
|
9 |
|
10 | No more need to write actions and reducer to update your store.
|
11 |
|
12 | What precisely each manager ?
|
13 |
|
14 | * It use CRUD pattern
|
15 | * update your data localy (redux store)
|
16 | * update your data localy AND sync at the same time to your remote server
|
17 | * update your data localy, and save few moment later to your remote server
|
18 | * indicate loading process to the user (for example with a loader). No need to manually set a ```isLoading``` flag.
|
19 | * fetch your data and use local data (redux) if resource are already fetched.
|
20 |
|
21 | Reudx Crud Manager do not include any library around redux, and do not provide any UI component. It only provide actions and reducer.
|
22 |
|
23 | ## Documentation:
|
24 |
|
25 | * [Configuration](#configuration)
|
26 | * [Simple Example](#simple-example)
|
27 | * [Configure remoteActions](docs/remote-actions.md)
|
28 | * [Configure reducer](docs/reducer.md)
|
29 |
|
30 | ### Configuration
|
31 |
|
32 | Install from npm registry
|
33 | ```
|
34 | npm install redux-crud-manager --save
|
35 | ```
|
36 |
|
37 | <a id="configuration"></a>
|
38 |
|
39 | ```js
|
40 | import { createManager } from 'redux-crud-manager';
|
41 |
|
42 | const config = {...};
|
43 | const usersManager = createManager(config);
|
44 | ```
|
45 |
|
46 | ### Config object
|
47 |
|
48 |
|
49 |
|
50 | * ```reducerPath``` {array[string]} - required - Most of time, there is a single item: the reducer name. But is you have nested reducer, define the full path.
|
51 |
|
52 |
|
53 | * ```remoteActions``` {object} - required - async action for HTTP request
|
54 |
|
55 |
|
56 | * ```idKey``` {string} - optional - the key use as the unique identifier. Default: ```id```
|
57 |
|
58 |
|
59 | * ```cache``` {bool | function} - enable cache if resources are already fetched. Default: ```false```
|
60 | You can pass a function to customise the check:
|
61 | ```js
|
62 | {
|
63 | cache: (existingItems) => existingItems[0] && existingItems[0].bookId === someBookId
|
64 | }
|
65 | ```
|
66 |
|
67 |
|
68 | * ```merge``` {bool} optional - default ```true``` - merge item property on update()
|
69 |
|
70 |
|
71 | * ```replace``` {bool} optional - default ```false```
|
72 |
|
73 |
|
74 | * ```remote``` {false} optional - default: ```false``` - save your change in your server, with remoteActions
|
75 |
|
76 |
|
77 | * ```prefixLocalId``` {string} - optional
|
78 |
|
79 |
|
80 | * ```showUpdatingProgress``` {bool} optional - default ```true```
|
81 |
|
82 |
|
83 | * ```updateLocalBeforeRemote``` {bool} optional - default ```false```. Ignored if ```showUpdatingProgress``` is false
|
84 |
|
85 |
|
86 | * ```forceDelete``` {bool} optional - default ```true```
|
87 |
|
88 |
|
89 | * ```includeProperties``` {array[string]} optional - include property on save.
|
90 |
|
91 |
|
92 | * ```excludeProperties``` {array[string]} optional - include property on save. Ignored if ```includeProperties``` is defined
|
93 |
|
94 |
|
95 |
|
96 | <a id="simple-example"></a>
|
97 |
|
98 | ### Simple example
|
99 |
|
100 | ```js
|
101 | import { createManager } from 'redux-crud-manager';
|
102 |
|
103 | const config = {
|
104 | reducerPath: ['users'],
|
105 | remoteActions: {
|
106 | fetchAll: () => {...}
|
107 | fetchOne: () => {...}
|
108 | create: () => {...}
|
109 | update: () => {...}
|
110 | delete: () => {...}
|
111 | }
|
112 | }
|
113 |
|
114 | const usersManager = createManager(config);
|
115 | ```
|
116 |
|
117 | * [How configure remoteActions](docs/remote-actions.md)
|
118 |
|
119 | How to create a user localy into redux store ?
|
120 | ```js
|
121 | const user = {name: ...};
|
122 | dispatch(usersManager.actions.create(user));
|
123 | ```
|
124 |
|
125 | Well, but with many users ?
|
126 |
|
127 | Use an array:
|
128 | ```js
|
129 | const users = [{name: ...}, {name: ...}];
|
130 | dispatch(usersManager.actions.create(users));
|
131 | ```
|
132 |
|
133 | How to create on my remote server ?
|
134 |
|
135 | Use ```{remote: true}```:
|
136 |
|
137 | ```js
|
138 | dispatch(usersManager.actions.create(users, {remote: true}));
|
139 | ```
|
140 |
|
141 | Here is what happens above:
|
142 | * POST request to your server
|
143 | * redux store update after the request response
|
144 |
|
145 | The POST request is defined in your remoteActions.create() function in the configuration.
|
146 | See [How configure remoteActions](docs/remote-actions.md)
|
147 |
|
148 | Now, if I want to do many changes localy, and sync my changes with my remote server few minutes later ?
|
149 |
|
150 | ```js
|
151 | // update my first user
|
152 | dispatch(usersManager.actions.update({id: 1, name: ...}));
|
153 |
|
154 | // create a third user
|
155 | dispatch(usersManager.actions.create({name: ...}));
|
156 |
|
157 | // delete my second user
|
158 | dispatch(usersManager.actions.delete(userId));
|
159 |
|
160 | // ... and few minute later, you want to save your data on your server
|
161 |
|
162 | dispatch(usersManager.actions.sync());
|
163 | ```
|
164 |
|
165 | Here is what happens above:
|
166 | * PATCH (or PUT) request to your server (update the first user)
|
167 | * POST request to your server (create the thrid user)
|
168 | * DELETE request to your server (delete the second user)
|
169 | * redux store update after all requests response
|
170 |
|
171 | The ```sync()``` function check which local resource was updated without ```{remote: true}``` option, and make the appropriate request for it (create, update or delete).
|
172 |
|
173 | ReducCrudManager use metadata to keep the state of your resource sync with your server, and know which resource need to be synced (created, updated or deleted).
|
174 |
|
175 | Ok, nice. But how I can notify my user that my application is making a server request, in order to show a loader ?
|
176 | Use metadata.
|
177 |
|
178 | ```js
|
179 | import {meta} from 'redux-crud-manager';
|
180 |
|
181 | const user = store.getState().users.find(...);
|
182 |
|
183 | if (meta(user).syncing) {
|
184 | // show loader
|
185 | }
|
186 | ```
|
187 |
|
188 | metadata are defined for a resource, and also for the list of resources:
|
189 |
|
190 | ```js
|
191 | import {meta} from 'redux-crud-manager';
|
192 |
|
193 | const users = store.getState().users;
|
194 |
|
195 | if (meta(users).syncing) {
|
196 | // show loader
|
197 | }
|
198 | ```
|
199 |
|
200 | Why we need to use ```meta(user).synced``` instead of ```user.synced``` ?
|
201 |
|
202 | Because metadata is store into a key symbol in order to prevent conflict var name.
|
203 |
|
204 | List of all metadata:
|
205 |
|
206 | | key | values | description |
|
207 | |:-------|:------|:------|
|
208 | |syncing|true / false|indicated if local data is currently syncing into server|
|
209 | |synced|true / false|indicated if local data is synced with server data|
|
210 | |fetching|true / false|only for resources list, not a single resource|
|
211 | |fetched|true / false|only for resources list, not a single resource|
|
212 | |nextSync|create / update / delete|indicated what is the next action for sync the local data to the server|
|
213 |
|
214 |
|
215 | ### TODO
|
216 | * save time of the last sync
|
217 | * use delay for cache fetching
|
218 |
|
\ | No newline at end of file |