Experimenting with normalizr#350
Experimenting with normalizr#350machour wants to merge 13 commits intogitpoint:masterfrom machour:redux-normalizr
Conversation
| @@ -0,0 +1,482 @@ | |||
| import { normalize, schema } from 'normalizr'; | |||
There was a problem hiding this comment.
This is the old api/index.js file, with some additions in the end : The client api.middleware uses to query the REST api and paginate the results
| import { eventSchema } from '../event/event.schema'; | ||
|
|
||
| // Schemas for Github API responses. | ||
| export const Schemas = { |
There was a problem hiding this comment.
Schemas are used by Normalizr to understand the JSON structure
| @@ -0,0 +1,10 @@ | |||
| export * from '../event/event.type'; | |||
There was a problem hiding this comment.
Making all types available in this file.
| onPress={() => this.navigateToRepository(userEvent, true)} | ||
| > | ||
| {userEvent.payload.forkee.full_name} | ||
| {userEvent.payload.forkee} |
There was a problem hiding this comment.
After normalization, userEvent.payload.forkee is simply the repo name (which can be later found in entities.repo)
| underlayColor={colors.greyLight} | ||
| onPress={() => navigation.navigate('Repository', { repository })} | ||
| onPress={() => | ||
| navigation.navigate('Repository', { name: repository.full_name })} |
There was a problem hiding this comment.
Most of our screens can be passed either a "string" or an "object" for the principal entity they're dealing with.
For example, user-profile can either take a login name, or a user object. This is really confusing and generate a lot of checks.
By switching to normalizer, we can now pass only the login, and let the middleware fetch the data from store or api :)
| forkee: repoSchema, | ||
| member: userSchema, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
This is one of my favorite files :)
We describe the event structure and link nested objects to their own schema
| showFullName | ||
| />} | ||
| onEndReachedThreshold={0.5} | ||
| onEndReached={() => getFollowers(login, true)} |
There was a problem hiding this comment.
this is how pagination is done :) Passing true as the second parameter for the data fetcher
|
|
||
| const orgs = []; | ||
|
|
||
| if (!user) { |
There was a problem hiding this comment.
Instead of doing this, we could draw the screen, display the information we already have (user avatar and name) and draw loading elements for the rest until the data is retrieved from the API.
|
|
||
| const { entities: { repos }, pagination: { reposByUser } } = state; | ||
| const reposPagination = reposByUser[login] || { ids: [] }; | ||
| const repositories = reposPagination.ids.map(id => repos[id]); |
There was a problem hiding this comment.
Here's how we reconstruct the repositories array, we fetch the ids from the pagination object and map them back to entities.repos
| { | ||
| idAttribute: user => user.login.toLowerCase(), | ||
| processStrategy: entity => | ||
| omit(entity, [ |
There was a problem hiding this comment.
All this fields can be guessed by having just the username. We remove them from the object to minimize our footprint
|
Finally, here's how to test this PR :
This is the only testable path so far. Here's how the redux store looks like during that :
|
| 'releases_url', | ||
| 'deployments_url', | ||
| ]), | ||
| } |
|
Deprecated by #457 |






This is not a real PR, but more a first experiment conducted using Redux with Normalizr, and some of my findings. Maybe this could lead to good ideas for the big refactoring due on our side to better handle the state.
As a reminder, our current Store problem is that we only have a user / repo in the state at runtime, and if you open two different profiles on two different screens, last data fetched is shown on both.
I came across https://github.com/reactjs/redux/tree/master/examples/real-world a few days ago, and decided to try to implement something similar in GitPoint.
The main idea is to have a Redux middleware taking care of most of the APIs calls, and normalizing the stored data into entities and paginations.
Here's what is working and worth looking at in this PR:
I'm going to comment some files changes in the diff to give some more insight.