redux middleware

master
Simon Rozsival 8 years ago
parent 5ebbc4ddf1
commit 3e7b68882a

@ -1627,7 +1627,7 @@ However due to the lack of time automatic monitoring of the backend state will
not be implemented in the early versions of this project but might be not be implemented in the early versions of this project but might be
implemented in some of the next releases. implemented in some of the next releases.
### The WebApp ### Web Application
The web application ("WebApp") is one of the possible client applications of the The web application ("WebApp") is one of the possible client applications of the
ReCodEx system. Creating a web application as the first client application has ReCodEx system. Creating a web application as the first client application has
@ -1711,15 +1711,17 @@ worth considering:
We decided to use React and Redux over Angular 2 for several reasons: We decided to use React and Redux over Angular 2 for several reasons:
- there is a large community arround these libraries and there is a large number - There is a large community arround these libraries and there is a large number
of tutorials, libraries, and other resources available online of tutorials, libraries, and other resources available online.
- many of the web frontend developers are familiar with React and Redux and - Many of the web frontend developers are familiar with React and Redux and
contributing to the project should be easy for them contributing to the project should be easy for them.
- Angular 2 was still not finished at the time we started developing the web - A stable version of Angular 2 was still not released at the time we started
application developing the web application.
- we had previous experience with React and Redux and Angular 2 did not bring - We had previous experience with React and Redux and Angular 2 did not bring
any significant improvements and features over React so it would not be worth any significant improvements and features over React so it would not be worth
learning the paradigms of a new framework learning the paradigms of a new framework.
- It is easy to debug React component tree and Redux state transitions
using extensions for Google Chrome and Firefox.
#### User Interface Design #### User Interface Design
@ -3122,9 +3124,28 @@ object and the action object and it creates a new state. This process is very ea
reason about and is also very easy to test using unit tests. Please read the reason about and is also very easy to test using unit tests. Please read the
[redux documentation](http://redux.js.org/) for detailed information about the library. [redux documentation](http://redux.js.org/) for detailed information about the library.
![Redux state handling schema](https://camo.githubusercontent.com/af8803571294fe373a54d039be8f9709f15a2ad4/687474703a2f2f6d616b6569746f70656e2e636f6d2f7374617469632f696d616765732f72656475785f666c6f7763686172742e706e67)
##### Redux Middleware ##### Redux Middleware
@todo A middleware in redux is a function which can process actions before they are passed
to the reducers to update the state.
The middleware used by the ReCodEx store is defined in the `src/redux/store.js` script.
Several open source libraries are used:
- [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware)
- [redux-thunk](https://github.com/gaearon/redux-thunk)
- [react-router-redux](https://github.com/reactjs/react-router-redux)
We created two other custom middleware functions to simplify the development:
- **API middleware** -- The middleware filters out all actions with the *type* set to `recodex-api/CALL`,
sends a real HTTP request according to the information in the action.
- **Access Token Middleware** -- This middleware persists the access token each time after the
user signs into the application into the local storage and the cookies. The token
is removed when the user decides to sign out. The middleware also attaches the token
to each `recodex-api/CALL` action when it does not have an access token set explicitly.
##### Accessing The Store Using Selectors ##### Accessing The Store Using Selectors
@ -3147,6 +3168,60 @@ Having up-to-date URLs gives the users the possibility to reload the page if som
error occurs on the page and land at the same page as he or she would expect. Users can also error occurs on the page and land at the same page as he or she would expect. Users can also
send links to the very page they want to. send links to the very page they want to.
### Creating HTTP Requests
All of the HTTP requests are made by dispatching a specific action which will be processed
by our custom *API middleware*. The action must have the *type* property set to
`recodex-api/CALL`. The middleware catches the action and it sends a real HTTP request
created according to the information in the `request` property of the action:
- **type** -- Type prefix of the actions which will be dispatched automatically during the
lifecycle of the request (pending, fulfilled, failed).
- **endpoint** -- The URI to which the request should be sent. All endpoints will be prefixed
with the base URL of the API server.
- **method** (*optional*) -- A string containing the name of the HTTP method which should be used.
The default method is `GET`.
- **query** (*optional*) -- An object containing key-value pairs which will be put
in the URL of the request in the query part of the URL.
- **headers** (*optional*) -- An object containing key-value paris which will be appended
to the headers of the HTTP request.
- **accessToken** (*optional*) -- Explicitly set the access token for the request. The token
will be put in the *Authorization* header.
- **body** (*optional*) -- An object or an array which will be recursively flattened into
the `FormData` structure with correct usage of square brackets for nested (associative)
arrays. It is worth mentioning that the keys must not contain a colon in the string.
- **doNotProcess** (*optional*) -- A boolean value which can disable the default procesing
of the response to the request which includes showing a notification to the user in case
of a failiure of the request. All requests are processed in the way described above
by default.
The HTTP requests are sent using the `fetch` API which returns a *Promise* of the request.
This promise is put into a new action and creates a new action containing the promise
and the type specified in the `request` description. This action is then caught by the
promise middleware and the promise middleware dispatches actions whenever the state of
the promise changes during its the lifecycle. The new actions have specific types:
- {$TYPE}_PENDING -- Dispatched immediatelly after the action is processed by the promise
middleware. The `payload` property of the action contains the body of the request.
- {$TYPE}_FAILED -- Dispatched if the promise of the request is rejected.
- {$TYPE}_FULFILLED -- Dispatched when the response to the request is received and the
promise is resolved. The `payload` property of the action contains the body of the
HTTP response parsed as JSON.
### Routine CRUD Operations
For routine CRUD (Create, Read, Update, Delete) operations which are common to most
of the resources used in the ReCodEx (e.g., groups, users, assignments, solutions,
solution evaluations, source code files) a set of functions called *Resource manager*
was implemented. It contains a factory which creates basic actions (e.g., `fetchResource`,
`addResource`, `updateResource`, `removeResource`, `fetchMany`) and handlers for
all of the lifecycle actions created by both the API middleware and the promise middleware
which can be used to create a basic reducer.
The *resource manager* is spread over several files in the `src/redux/helpers/resourceManager`
directory and is covered with unit tests in scripts located at
`test/redux/helpers/resourceManager`.
### Servier-side Rendering ### Servier-side Rendering
To speed-up the initial time of rendering of the web application a technique called server-side To speed-up the initial time of rendering of the web application a technique called server-side

Loading…
Cancel
Save