📜 ⬆️ ⬇️

Redux-Redents is (yet) one module for working with server data from React-Redux applications.

React and Redux, recently one of the most popular buzz-words in the world of frontend. So when I needed to make a web application that would display the data received from the server, and also allow them to manipulate (create, delete and modify), I decided to build it on the basis of a bunch of React and Redux. Many getting-started guides cover only the functionality of creating components, the action creators and reducers. But as soon as it comes to sharing with the server, difficulties begin - the number of necessary action creators, reducers grows. And they are very similar to each other, with minimal differences. In most cases - only in the type (name) of the activity. After I created the third identical set of creators and reducers, then there was a desire to change something. So the idea of ​​implementing redux-redents was born .


Start, dictionary reducers


In general, reducers are very similar to each other - to take your action and create a new storage state based on it. If we consider reducers to handle the response from the server, then they will differ only in the type of action. So the idea of ​​a "universal" reducer was born:


function createReducer(acttype,initialState) { return (state = initialState, action) => { if(action.type!=acttype) return state; return action.res.data; }; } const dicts = { type1 : createReducer(TYPE1_CONSTANT,{}), type2 : createReducer(TYPE2_CONSTANT,[]) } const rootReducer = combineReducers({...dicts}); 

Already it allows not to write the same functions and not fence the switch-case constructs.


Constants. Deliverance.


Dictionary reduers reduced the number of the same code, but there are constants to set the types of action. Adding a new action and its handler looks like this:


  1. create a constant for the action type
  2. create action creator
  3. create a createReducer handler with the specified type.

Support for a set of constants begins to annoy almost immediately. Moreover, there is practically no sense in them - the developer uses them only for the creator and reducer bundles. Thus, constants can be replaced with agreements for configuring action types.
Further, all the action creators for receiving data from the server look the same - to create an action with the necessary type and a promise to query the server. If they look the same, is it not better to automate the process of creating the creators, and even better to make the universal creator?


Combining the two ideas - replacing constants with conventions and the universal creator and led to the birth of the module.


Data Agreements


If rest-like api is used to communicate with the server, then for each data type we have the same number of default operations: index (list), get, post, delete; and each operation has uri and parameters for transfer to the server. Thus, default agreements can be entered into:



In addition, you must provide the possibility of expansion:



The result is the following format:


 entities = { fruit : {}, //all default vegetable: { crop : { //custom operation type: 'CROP_VEGETABLE', request: (data) => return post(url,data) //custom request }, index: { url: url1 //custom url } } } 

Universal action creator


Now, to simplify life, it remains to implement universal actions creator. And again agreements come to our aid:



The universal action creator allows you to do the following:


 this.props.entityOperation('fruit','index'); //   this.props.entityOperation('fruit','get','apple'); //    'apple' this.props.entityOperation('fruit','post',{name:'orange',id:'5'}); //   'orange' this.props.entityOperation('vegetable','crop',{name:'carrot'}); //  crop  parrot 

Creator creates an action with a promise to send / receive data to the server. Promise needs to be processed somehow and redux middleware comes to help here


Middlewares


Redux middleware is a function that accepts action and the next handler in the chain, and that can process the action itself and / or pass it further along the chain of handlers. To process promise, we need to accept the original action, install promise handlers and modify the action to show that the system is in the state of requesting data to the server. To modify, you can either add fields to the action, or modify its type. I chose a type modification.


Promise Middleware



Promises earned, data comes from the server, but there was a lack of the opportunity to call action after the completion of another. For example, update the data from the server after saving the data to it. Thus, Chain Middleware was invented, a function that executes the action creator after processing the previous action.


Chain middleware


To implement call chains, the last parameter to the universal action creator was added the generating new action function, which accepts the server’s response to the input (if it exists) or the original action (otherwise).
The generating function is called only if the processed action contains a status field with a value of 'done' (action.status == 'done')


 this.entityOperation('fruit','save',fruit,()=>this.props.entityOperation('fruit','index')); 

Module


The natural desire was to share these ideas and their implementation - the redux-redents module was born. The module is available for installation in npm


 npm install --save redux-redents 

Usage example


As an example, the developed "application" client-demo


 git clone https://github.com/kneradovsky/redents/ cd client-demo npm install npm start 

the last command will build the application, launch the development server and open the starting URL of the application in the browser
The application contains one page that displays a list of fruits and allows you to add, delete and edit fruits. View of the page in the screenshot below:


screenshot


Conclusion


I would be glad if my module would be useful. Open to questions, comments and suggestions for expanding functionality. The source code of the module, as always, is available in the GitHub repository.


')

Source: https://habr.com/ru/post/305074/


All Articles