Reputation: 29
I have only been using React and Redux for some months, and I have implemented Reselect recently in order to try and make the application faster. I can't get it to work the way I would like it to, and I'm not sure where the problem comes from.
I resumed the development of a Planning app for the dev department I work for. The main page can have a certain number of weeks, contained in a Row
. Each day of the week is a Component, and in each Day
Component, you may have a TimePlanned
Component. There is one Row
Component line per ticket affected to a developer, and there can be as many as 10 tickets per user, so...there are a lot of Components.
I implemented Reselect so that my many connected Components did not get re-rendered as often as they used to be with Redux alone.
I have a problem with the Day
Component. I am trying to have them access the smallest amount of data possible, to prevent the other Day
from re-rendering when they are not concerned about the change.
Here is what the data that I want to 'sort' might look like :
planifie:{
tickets : {
29859 : {
ticketId : 29859,
typeId : 1,
projectId : 6,
userId : 3;
planifications : [549],
comments : []
}
},
planifications : {
549 : {
planId : 549,
ticketId : 29859,
planDate : "2019-05-16",
planTime : 480,
userId : 3
},
550 : {
planId : 550,
ticketId : 29859,
planDate : "2019-05-16",
planTime : 480,
userId : 6
}
},
users : {
3 : {
userId : 3,
userName : "pdupont",
tickets : [29859],
comments : [],
planifications : [549]
}
}
}
There are, of course, several records for each 'category'.
My selectors looks like this :
export const getAllPlans = state => state.planifie.planifications
export const getGroup = state => _.find(state.filters.plannedFilters.groupBy, ['isActive', true])
export const getUserPropsId = (state,props) => props.userId
export const makeGetAllPlans = () => {
return createSelector(
getAllPlans,
plans => plans
)
}
export const makeGetRelevantObjectPlans = () => {
return createSelector(
[getAllPlans,getGroup,getUserPropsId],
(planifications,group,user) => {
switch (group.code) {
case 'project':
return _.filter(planifications, {projectId : user})
case 'user':
return _.filter(planifications, {userId : user})
case 'type':
return _.filter(planifications, {typeId : user})
}
}
)
}
The props.userId
is always a number, but if my planifications are sorted by projets, it will be equivalent to a projectId. The memoized selector's goal is to return the planifications
object relevant to the Id passed in props.
For this example, my filter is by user. I would like a Row
of my Day
components to only get access to the planifications with a '3' userId.
In my Day
Component, this is how I call the selector :
const makeMapStateToProps = () => {
const getComs = makeGetRelevantComments()
const getPlans = makeGetRelevantPlans()
const getPlanifications = makeGetRelevantObjectPlans()
const mapStateToProps = (state, props) => {
return {
coms : getComs(state,props),
plans : getPlans(state,props),
planifications : getPlanifications(state,props)
}
}
return mapStateToProps
}
const mapDispatchToProps = (dispatch) => (
bindActionCreators(ActionsCreators, dispatch)
)
export default connect(makeMapStateToProps, mapDispatchToProps)(Day)
I put a function in my componentDidUpdate()
to see what triggers re-renders, and on every Day
Component, even the ones with a different props.userId, the planifications
change, so my page takes very long to load.
For example, if I update the date of one planification with this Redux reducer action :
case types.SET_PLAN:
return {
...state,
planifie: {
...state.planifie,
planifications : {
...state.planifie.planifications,
[action.data.planId] : {
...state.planifie.planifications[action.data.planId],
...action.data.plan
}
}
},
isLoading: false
}
Then every single one of my Day Component gets re-rendered.
I am wondering if I am missing something in my code, if I misunderstood what a memoized selectors can do, if the lodash filter
function prevents is interfering with the immutability of the code, or if my data is not formated for this type of thing.
Thank you.
Upvotes: 0
Views: 279
Reputation: 334
I ran through your code and there very few things that might be helpful:
1.getGroup
selector must be memoized, because after each update of store _.find
will return new Array and memoization for makeGetRelevantObjectPlans
will be broken.
So getGroup
might look like:
const groupBy = state => state.filters.plannedFilters.groupBy;
const getGroup = createSelector(
[groupBy],
(groupBy) => _.find(groupBy, ['isActive', true]),
);
createStructuredSelector
instead of makeMapStateToProps
might also be helpfulUpvotes: 1