1 | # @wildberries/redux-core-modules
|
2 |
|
3 | ## Sollution for redux and redux-saga common cases
|
4 |
|
5 | ### What does it provide:
|
6 |
|
7 | - Store initialization
|
8 | - Core redux-modules for common usage
|
9 | - Utils for redux code-splitting
|
10 |
|
11 | #### installation
|
12 |
|
13 | ```javascript
|
14 | npm install @wildberries/redux-core-modules
|
15 | ```
|
16 |
|
17 | ## Features:
|
18 |
|
19 | ### Store initialization:
|
20 |
|
21 | ```javascript
|
22 | import React from 'react';
|
23 | import ReactDOM from 'react-dom';
|
24 | import { Provider } from 'react-redux';
|
25 | import { configureRouter } from '@wildberries/service-router';
|
26 | import { createAppStore } from '@wildberries/redux-core-modules';
|
27 |
|
28 | const ROOT_ELEMENT = document.getElementById('root');
|
29 |
|
30 | const router = configureRouter({ defaultRoute: 'wb-eu-registration' });
|
31 |
|
32 | const store = createAppStore({
|
33 | router,
|
34 | });
|
35 |
|
36 | router.start(() => {
|
37 | ReactDOM.render(
|
38 | <Provider store={store}>
|
39 | <App />
|
40 | </Provider>,
|
41 | ROOT_ELEMENT,
|
42 | );
|
43 | });
|
44 | ```
|
45 |
|
46 | ### Core redux-modules for common usage:
|
47 |
|
48 | - Form-manager-module - helps to work with the form submission
|
49 | - Init-load-manager-module - helps to get data when page is rendering
|
50 | - Redirect-manager-module - helps to navigate in redux-saga worker saga
|
51 | - Request-extra-data-handler-module - helps to make different actions from response data
|
52 | - UI-module - helps with working in the whole app ui-data
|
53 |
|
54 | ### Form-manager-module - gets options and make request and handle different operations:
|
55 |
|
56 | - re-save form data (necessary for react-final-form) before call the request and set new data
|
57 | - format form data before to insert to the request
|
58 | - start and stops form loading state
|
59 | - call error action (of array of actions)
|
60 | - call success action (of array of actions)
|
61 | - trigger notifications actions on success and error
|
62 | - send data (formatted of not) to the Request-extra-data-handler-module to make some operations with splitted data from response
|
63 | - trigger success or error router redirections
|
64 |
|
65 | #### Example:
|
66 |
|
67 | ```javascript
|
68 | import { fetchFormManagerSagaAction } from '@wildberries/redux-core-modules';
|
69 |
|
70 | const formManagerSubmitOptions: FormManagerType = {
|
71 | formValues: { foo:'bar' },
|
72 | loadingStartAction: ()=>({ type:'loading start' }),
|
73 | loadingStopAction: ()=>({ type:'loading stop' }),
|
74 | formValuesFormatter: (data) => ({ 'baz':data.foo }),
|
75 | formRequest: fetch('http://example.com'),
|
76 | formSuccessAction: (payload)=>({ type:'some example success action', payload }),
|
77 | setErrorAction: (payload)=>({ type:'some example error action', payload }),
|
78 | resetInitialDataAction: (payload)=>({ type:'action to re-save form data', payload }),
|
79 | showNotification: true,
|
80 | redirectSuccessActionParams: {
|
81 | pathName: 'some.path',
|
82 | },
|
83 | };
|
84 |
|
85 | store.dispatch(formManagerSubmitOptions);
|
86 | ```
|
87 |
|
88 | ### Init-load-manager-module - has the separate config for each request and makes operations:
|
89 |
|
90 | - start and stop form loading state (not in each request but in the whole action)
|
91 | - format request data before and after the request
|
92 | - get the options (or not) and calls the request
|
93 | - trigger notifications actions on success and error
|
94 | - call error action (of array of actions)
|
95 | - call success action (of array of actions)
|
96 | - send data (formatted of not) to the Request-extra-data-handler-module to make some operations with splitted data from response
|
97 | - trigger success or error router redirections
|
98 | - ability to use batching (in JSON-RPC protocol)
|
99 | - cancelling the request if not responded
|
100 |
|
101 | #### Example:
|
102 |
|
103 | ```javascript
|
104 | import { initLoadManagerActionSaga, InitLoadManagerActionPayloadType } from '@wildberries/redux-core-modules';
|
105 | import { getWarehousesListRequest } from '@/services/api/requests/get-warehouses-list';
|
106 | import { getCountriesListRequest } from '@/services/api/requests/get-countries-list';
|
107 | import { setRegionsAction } from '../_redux/regions-module';
|
108 | import { setWarehousesAction } from '../_redux/warehouses-module';
|
109 | import { warehousesListFormatter } from '../_utils/warehouses-list-formatter';
|
110 |
|
111 | const loadDataConfig: InitLoadManagerActionPayloadType = {
|
112 | requestConfigList: [
|
113 | {
|
114 | request: getWarehousesListRequest,
|
115 | requestOptions: { foo:'bar' },
|
116 | isDataCritical: true,
|
117 | showErrorNotification: true,
|
118 | showSuccessNotification: false,
|
119 | requestDataFormatter: warehousesListFormatter,
|
120 | actionSuccess: setWarehousesAction,
|
121 | isBatchRequest: true
|
122 | },
|
123 | {
|
124 | request: getCountriesListRequest,
|
125 | isDataCritical: true,
|
126 | showErrorNotification: true,
|
127 | showSuccessNotification: false,
|
128 | requestExtraDataHandlerOptions: [
|
129 | {
|
130 | fieldName: 'countries',
|
131 | action: setRegionsAction,
|
132 | },
|
133 | ],
|
134 | },
|
135 | ],
|
136 | };
|
137 |
|
138 | store.dispatch(initLoadManagerActionSaga(loadDataConfig));
|
139 | ```
|
140 |
|
141 | ### Download-files-manager-module - manager to download base64 and blob type files:
|
142 |
|
143 | - start and stop form loading state
|
144 | - format request data before to get file to be downloaded
|
145 | - get the options (or not) and calls the request
|
146 | - trigger notifications actions on success and error
|
147 | - call error action (of array of actions)
|
148 | - call success action (of array of actions)
|
149 |
|
150 | #### Example:
|
151 |
|
152 | ```javascript
|
153 | import { downloadFilesManagerSagaAction, DownloadFilesManagerType } from '@wildberries/redux-core-modules';
|
154 | import { someDownloadRequest } from '@/services/api/requests/some-request';
|
155 | import { getCountriesListRequest } from '@/services/api/requests/get-countries-list';
|
156 | import { setRegionsAction } from '../_redux/regions-module';
|
157 | import { setWarehousesAction } from '../_redux/warehouses-module';
|
158 |
|
159 | const config: DownloadFilesManagerType = {
|
160 | downloadFileRequest: someDownloadRequest,
|
161 | requestParams: {foo: 'bar'};
|
162 | loadingStartAction: () => ({ type:"LOADING_START" });
|
163 | loadingStopAction: () => ({ type:"LOADING_STOP" });
|
164 | formSuccessAction: () => ({ type:"SOME_SUCCESS_ACTION" });
|
165 | formSuccessActionsArray: [
|
166 | () => ({ type:"SOME_SUCCESS_ACTION_1" }),
|
167 | () => ({ type:"SOME_SUCCESS_ACTION_2" })
|
168 | ]
|
169 | setErrorAction: () => ({ type:"SOME_ERROR_ACTION" });
|
170 | setErrorActionsArray: [
|
171 | () => ({ type:"SOME_ERROR_ACTION_1" }),
|
172 | () => ({ type:"SOME_ERROR_ACTION_2" })
|
173 | ]
|
174 | showNotificationError: true;
|
175 | showNotificationSuccess: true;
|
176 | notificationSuccessMessage: 'some success notification message';
|
177 | fileType: 'base64';
|
178 | };
|
179 |
|
180 | store.dispatch(downloadFilesManagerSagaAction(config));
|
181 | ```
|
182 |
|
183 | ### Redirect-manager-module - simple options-provider to the router.navigate method from router5:
|
184 | - redirects to internal routes
|
185 | - redirects to external routes (for example if you are using microservice architecture and you stream-app doesn't know about external routes)
|
186 |
|
187 | #### provides actions:
|
188 | ```javascript
|
189 | import { redirectManagerSagaAction, redirectToPlatformRouteManagerSagaAction } from '@wildberries/redux-core-modules';
|
190 |
|
191 | store.dispatch(redirectManagerSagaAction({
|
192 | pathName: 'route.path.name';
|
193 | params: { foo:'bar' };
|
194 | actionAfterRedirect: (payload) => ({ type:'action that will be called after redirect', payload })
|
195 | actionAfterRedirectParams: { id: 'test_id' };
|
196 | }));
|
197 |
|
198 | 'there is no differences between action signatures - they are actually go to the one watcher-saga'
|
199 | 'but to show exactly where do you want to redirect - we provide this method'
|
200 |
|
201 | store.dispatch(redirectToPlatformRouteManagerSagaAction({
|
202 | pathName: 'route.path.name';
|
203 | params: { foo:'bar' };
|
204 | actionAfterRedirect: (payload) => ({ type:'action that will be called after redirect', payload })
|
205 | actionAfterRedirectParams: { id: 'test_id' };
|
206 | }));
|
207 | ```
|
208 |
|
209 | ### Request-extra-data-handler-module:
|
210 | - gets the data and array of options to process this data with redux-actions
|
211 |
|
212 | #### provides actions:
|
213 | ```javascript
|
214 | import { requestExtraDataHandlerActionSaga, RequestExtraDataHandlerActionSagaType } from '@wildberries/redux-core-modules';
|
215 |
|
216 | store.dispatch(requestExtraDataHandlerActionSaga({
|
217 | data: {
|
218 | field1: {
|
219 | foo: 'bar'
|
220 | },
|
221 | field2: {
|
222 | someOption: [
|
223 | { foo:'bar' }
|
224 | ]
|
225 | }
|
226 | },
|
227 | options: [
|
228 | {
|
229 | fieldName: 'field1';
|
230 | action: (payload) => ({ type:'action that will be called with the field1 data', payload })
|
231 | },
|
232 | {
|
233 | fieldName: 'field2';
|
234 | action: (payload) => ({ type:'action that will be called with the field2 data', payload })
|
235 | },
|
236 | ]
|
237 | }));
|
238 | ```
|
239 |
|
240 | ### requestErrorHandlerProcess util:
|
241 | - gets the request
|
242 | - provide the validation for the request
|
243 | - dispatches an action or an array of actions if the response is invalid
|
244 | - options for that feature exist in Form-manager-module and in Init-load-manager-module
|
245 |
|
246 | ```javascript
|
247 | import { requestErrorHandlerProcess } from '@wildberries/redux-core-modules';
|
248 |
|
249 | // inside the saga
|
250 | const validatedData = yield* requestErrorHandlerProcess({
|
251 | request: () =>
|
252 | updateReportRequest({
|
253 | id,
|
254 | status: STATUS_APPROVED,
|
255 | }),
|
256 | requestValidator: () => false,
|
257 | errorAction: () => ({ type: 'test error action' }),
|
258 | });
|
259 | ```
|
260 |
|
261 | ## Utils for redux code-splitting:
|
262 |
|
263 | ### inject reducers:
|
264 |
|
265 | ```javascript
|
266 | import { injectAsyncReducer } from '@wildberries/redux-core-modules';
|
267 |
|
268 | injectAsyncReducer({
|
269 | store, '-- pure store object'
|
270 | name: 'registrationFormStorage', '-- reducer name'
|
271 | reducer: registrationFormStorage, '-- reducer instance'
|
272 | });
|
273 | ```
|
274 |
|
275 | ### inject sagas:
|
276 |
|
277 | ```javascript
|
278 | import { injectAsyncSaga } from '@wildberries/redux-core-modules';
|
279 |
|
280 | injectAsyncSaga({
|
281 | store, '-- pure store object'
|
282 | name: 'downloadContractOfferWatcherSaga', '-- saga name'
|
283 | saga: downloadContractOfferWatcherSaga, '-- saga instance'
|
284 | });
|
285 | ```
|
286 |
|
287 | ### remove sagas:
|
288 |
|
289 | ```javascript
|
290 | import { removeAsyncSaga } from '@wildberries/redux-core-modules';
|
291 |
|
292 | removeAsyncSaga({
|
293 | store, '-- pure store object'
|
294 | name: 'downloadContractOfferWatcherSaga', '-- saga name'
|
295 | });
|
296 | ```
|
297 |
|
298 | ### remove reducers:
|
299 | ### Warning - please be accurate with this. You can lose your necessary data !
|
300 |
|
301 | ```javascript
|
302 | import { removeAsyncReducer } from '@wildberries/redux-core-modules';
|
303 |
|
304 | removeAsyncReducer({
|
305 | store, '-- pure store object'
|
306 | name: 'registrationFormStorage', '-- saga name'
|
307 | });
|
308 | ```
|