title | author | image | tags | redirect_to | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Refactoring sensenet's redux library |
herflis |
../img/posts/snredux-refactor.jpeg |
|
We've continued refactoring client side packages with sn-redux. Similarly to sn-client-js related new scoped packages, the changes were about removing dependence on rxjs, improving the API, review other dependencies and making some clean-ups.
Following will sum up all the changes, the why's and how's including a list of the possible migration steps if you used a previous version of sn-redux before.
As it was mentioned in one of our previous posts, with creating scoped packages our main goal was to divide the code into smaller and more maintainable units. We've created @sensenet scope and publish our npm packages within this. With sn-redux the plan was the same, so @sensenet/redux was born. From now on the package should be installed like this:
npm install --save @sensenet/redux
This way it will be saved in a separate folder named @sensenet and the inner modules have to be imported this way:
import { Actions } from '@sensenet/redux'
The list of dependencies of previous versions was quite huge so we've decided to think about how to reduce the number of them. First step was to remove everything related to gulp. Since the last version we only use it in one task to help generating docs with typedoc, but it became unnecessary with some improvements in our npm scripts so gulp related dependencies could have been removed. Some of the tools were removed because they add tons of dependencies indirectly while they're necessary only in our development process, so because of this we decided to install things like typedoc or commitizen as global dependencies in the future this way they could be removed from the list of dependencies.
The biggest improvement of the new release was refactoring async operations. We have been using rxjs and redux-observable for this purposes for a while but it became more and more complicated to keep our code up-to-date, testable and maintainable with these two. The plan was to check some of the potential competitors of redux-observable and set an order along complexity, typesafety, number of dependencies and maintainability. We tried redux-promise-middleware, redux-thunk, redux-saga and the potential of native es6 promises and at the first site redux-promise-middleware was the one. After a while it came out that even though it fits our needs in many cases it doesn't do it in others. Sensenet repository is needed in all the levels of action creators and redux-promise-middleware doesn't support using custom input params or any other ways to solve this issue for us. So we created our custom middleware based on redux-promise-middleware with repository as possible input param and with adding some other minor things like changing the action delimiter and action suffixes. sn-redux-promise-middleware is of course in the @sensenet scope and it became a dependency of sn-redux.
One of the main purposes of replacing rxj was that some part of the code was and would have been always untestable and also the coverage could not have been improved above a certain level. Creating a custom middleware lets us reach every level of the code and this way we were able to maximaze the code coverage to 100%.
Besides that number of tests and the code coverage was improved we set higher standards in linting rules of the project as well.
Huge part of the documentation became pretty outdated because of the numerous changes of the API, so it was clear that it need to be revisited and fixed. Since we've added linting rules to force us documenting public stuff, no undocumented code is allowed and the API docs of the current version are complete. Docs are moved to sensenet's community site so you can discover it in depth.
As I mentioned it above while we were updating our test projects like sn-dms-demo, we've made a list of issues and of course the possible solutions. If you have used sn-redux before and thinking of the upgrade, the following checklist makes you sure that it could be done with only a few changes.
import { Reducers } from '@sensenet/redux'
import { Repository } from '@sensenet/client-core'
const repository = new Repository({
repositoryUrl: 'https://mysite.com',
requiredSelect: ['Id', 'Path', 'Name', 'Type', 'ParentId', 'Actions', 'Avatar'] as any,
})
import { JwtService } from '@sensenet/authentication-jwt'
const jwt = new JwtService(repository)
- Way of creating and configuring a sensenet redux store has changed. You have to create a CreateStoreOptions
object and use it as the only input param of createSensenetStore
import { Reducers, Store } from '@sensenet/redux'
const options = {
repository,
rootReducer: myReducer,
} as Store.CreateStoreOptions
const store = Store.createSensenetStore(options)
export const userRegistration = (email: string, password: string) => ({
type: 'USER_REGISTRATION_REQUEST',
email,
password,
async payload(repository: Repository) {
const data = await repository.executeAction({
name: 'RegisterUser', idOrPath: `/Root/IMS('Public')`, body: {
email,
password,
}, method: 'POST',
})
},
})
- Since the success and reject actions are handled in the background you cannot dispatch them manually.
- If you've created an Epic not for handling async operations but for subscribing on actions you have to subscribe separately after configuring the store.
For example I've created a MessageBoxHandler
in the dms-demo to subscribe on the onContentDeleteFailed
and onContentDeleted
events and added this handler after the store creation like:
const store = Store.createSensenetStore(options)
const handler = new MessageBoxHandler(repository, store)
Check your custom Reducers that are connected with built-in sn-redux actions.
Since the API is ready we can update our React controls package as well.
We also plan to update our command line tool to allow developers fetching their content types from CTDs but before we do that we want to improve the client-side schema loading.
Meanwhile we're working on independent components like the Document viewer, creating demo apps like sn-dms-demo and trying to provide you more and more docs and tutorials on sensenet community site.
We are open and want to build a great community around sensenet so your opinion is super important to us. Please try, review and comment our work and help us make the world a better place! 😻