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