-
Notifications
You must be signed in to change notification settings - Fork 783
Add reselect and redux actions to organizations #269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
import { createSelector } from 'reselect'; | ||
import { getOrganization as getOrganizationFromStore } from '../../root.reducer'; | ||
|
||
export const getOrganization = createSelector( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Benefits of using reselect
instead of querying the store by.doing.something.like.this
Selectors can compute derived data, allowing Redux to store the minimal possible state.
Selectors are efficient. A selector is not recomputed unless one of its arguments change.
Selectors are composable. They can be used as input to other selectors.
More info https://github.com/reactjs/reselect
getOrganizationIsPendingMembers, | ||
} from '../index'; | ||
|
||
const selectors = createStructuredSelector({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be almost the same as mapStateToProps
but it uses reselect.
@@ -1,5 +0,0 @@ | |||
import { createActionSet } from 'utils'; | |||
|
|||
export const GET_ORG = createActionSet('GET_ORG'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got rid of this *.type.js
file in favor of *.constants.js
and *.actions.js
files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice this is perfect, using redux-actions
looks like we don't need a helper utility like createActionSet
whatsoever
}; | ||
|
||
export const organizationReducer = (state = initialState, action = {}) => { | ||
switch (action.type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got rid of this ugly switch
statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OMG how have I not used redux-actions
before, it looks so much cleaner 😍
@@ -7,63 +19,65 @@ const initialState = { | |||
isPendingOrg: false, | |||
isPendingRepos: false, | |||
isPendingMembers: false, | |||
error: '', | |||
organizationError: '', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created one error for organization, another for repositories and another for members.
@@ -0,0 +1,3 @@ | |||
import { Record } from 'immutable'; | |||
|
|||
// WIP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Immutable work should go here =)
|
||
dispatch({ type: GET_ORG.PENDING }); | ||
export const getOrg = createAction(GET_ORG); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating actions by using redux-actions I think this is more organized than have a manual dispatch with some boilerplate like {type: ... , payload: ...}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice agreed, makes things look so much more oganized 👍
root.reducer.js
Outdated
@@ -16,3 +16,7 @@ export const rootReducer = combineReducers({ | |||
search: searchReducer, | |||
notifications: notificationsReducer, | |||
}); | |||
|
|||
// Used to get organization information in selectors | |||
export const getOrganization = state => state.organization; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used in the selectors to get some data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks so good @alejandronanez. Can't explain how much things are already looking cleaner.
Just left a few discussion points, but otherwise I can't see anything I would change outright.
}; | ||
|
||
export const organizationReducer = (state = initialState, action = {}) => { | ||
switch (action.type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OMG how have I not used redux-actions
before, it looks so much cleaner 😍
@@ -1,5 +0,0 @@ | |||
import { createActionSet } from 'utils'; | |||
|
|||
export const GET_ORG = createActionSet('GET_ORG'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice this is perfect, using redux-actions
looks like we don't need a helper utility like createActionSet
whatsoever
|
||
dispatch({ type: GET_ORG.PENDING }); | ||
export const getOrg = createAction(GET_ORG); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice agreed, makes things look so much more oganized 👍
|
||
export const getOrganization = createSelector( | ||
getOrganizationFromStore, | ||
organization => organization.organization || {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was having a disussion with colleagues from work this past week and a few were under the impression that when simply getting object parameters with dot notation doesn't necessarily need createSelector
. For example, this would be sufficient:
export const getOrganization = state => state.organization.organization;
Not necessarily sure if I agree however. Majority of all our selectors are simple getters and not involve manipulation of data in anyway so it seems if we went with this approach we wouldn't really be using createSelector
for the majority of our state.
Just wanted to get your input on this mate. Do you usually use createSelector
for all data or only if you're retrieving data and performing manipulation to it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey dude! I usually use it to query the store and do some computations based on that data when needed. The big plus I see is that we can compose any selectors we want, for example combine one selector from organizations, one from repos and two from auth, then produce a new prop to pass to any component we want. I truly believe this is a good adition to the stack.
Here's a copy paste from reselect's site
Selectors can compute derived data, allowing Redux to store the minimal possible state.
Selectors are efficient. A selector is not recomputed unless one of its arguments change.
Selectors are composable. They can be used as input to other selectors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a million again for this <3<3<3<3<3<3<3<3
Should we have a separate issue open to track adding reselect and redux-actions to all the other parts of the app?
@housseindjirdeh yes! I think that's the right approach! 🙌🏼 |
Hey there!
I have a WIP branch with some updates on our codebase, it is still not done but I want to get early feedback on what I have here.Will update this description as I make more progress - thanks for your patience!Update
I completed my work on this but I decided to not include
Immutable
(not in this PR at least), because reselect + redux actions can live without Immutable.So, the structure of the code has changed slightly, it goes like:
organization.selectors.js
file. Here we're usingreselect
https://github.com/reactjs/reselect to "query" our store and get the data we need (reselect also has a bunch of benefits that you can read in their docs). This will save us some duplication when we want to get data from the store in different containers (we should reuse the selectors we have in the selectors file whenever we want to use an specific part of the state)organization.constants.js
file, I took this approach because we can use the constants through our reducers and actions (and in our tests in the future) also, I find the*.type.js
notation quite ambiguousswitch
statement in our reducer (I love this part)