Reputation: 589
I've been stuck on this for a while.
Here's a part of my redux-state
state: {
teachers: [
{ teacherId: 'ttt1', teacherName: 'Susan', isCool: true, teachesAt: 'sss1'},
{ teacherId: 'ttt2', teacherName: 'Karen', isCool: false, teachesAt: 'sss2'},
{ teacherId: 'ttt3', teacherName: 'Bob', isCool: true, teachesAt: 'sss3'},
{ teacherId: 'ttt4', teacherName: 'Mike', isCool: false, teachesAt: 'sss1'},
],
schools: [
{ schoolId: 'sss1', schoolName: 'Washington'},
{ schoolId: 'sss2', schoolName: 'Lincoln'},
{ schoolId: 'sss3', schoolName: 'Jefferson'},
],
students: [
{ schoolIdEnrolled: 'sss1', studentName: 'Billy'},
{ schoolIdEnrolled: 'sss1', studentName: 'Steven'},
{ schoolIdEnrolled: 'sss2', studentName: 'Bobby'},
{ schoolIdEnrolled: 'sss3', studentName: 'Mikey'},
{ schoolIdEnrolled: 'sss3', studentName: 'Sally'},
{ schoolIdEnrolled: 'sss3', studentName: 'Cindy'},
{ schoolIdEnrolled: 'sss3', studentName: 'Mandy'},
],
classes: [...],
}
Can anyone dream up a way so that in the render method of my
React Component I can loop through my schools and calculate the number
of 'coolTeachers'
and 'studentCount'
for each school? Is this the
use-case for reselect?
My table needs to be like this:
SCHOOL______# OF COOL TEACHERS_______STUDENTS
Washington__________1_______________________2
Lincoln______________0_______________________1
Jefferson____________1_______________________4
Upvotes: 4
Views: 85
Reputation: 31024
This is classic usecase for Array.prototype.reduce
:
const state = {
teachers: [
{ teacherId: 'ttt1', teacherName: 'Susan', isCool: true, teachesAt: 'sss1'},
{ teacherId: 'ttt2', teacherName: 'Karen', isCool: false, teachesAt: 'sss2'},
{ teacherId: 'ttt3', teacherName: 'Bob', isCool: true, teachesAt: 'sss3'},
{ teacherId: 'ttt4', teacherName: 'Mike', isCool: false, teachesAt: 'sss1'},
],
schools: [
{ schoolId: 'sss1', schoolName: 'Washington'},
{ schoolId: 'sss2', schoolName: 'Lincoln'},
{ schoolId: 'sss3', schoolName: 'Jefferson'},
],
students: [
{ schoolIdEnrolled: 'sss1', studentName: 'Billy'},
{ schoolIdEnrolled: 'sss1', studentName: 'Steven'},
{ schoolIdEnrolled: 'sss2', studentName: 'Bobby'},
{ schoolIdEnrolled: 'sss3', studentName: 'Mikey'},
{ schoolIdEnrolled: 'sss3', studentName: 'Sally'},
{ schoolIdEnrolled: 'sss3', studentName: 'Cindy'},
{ schoolIdEnrolled: 'sss3', studentName: 'Mandy'},
],
}
const teachersReducer = (teachers, id) => {
const numOfteachers = teachers.reduce((result, current) => {
if (current.teachesAt === id && current.isCool) {
result++;
}
return result;
}, 0);
return numOfteachers;
}
const studentsReducer = (students, id) => {
const numOfstudents = students.reduce((result, current) => {
if (current.schoolIdEnrolled === id) {
result++;
}
return result;
}, 0);
return numOfstudents;
}
const resultData = state.schools.reduce((result, currentSchool) => {
const currentId = currentSchool.schoolId;
const numOfTeachers = teachersReducer(state.teachers, currentId);
const numOfStudents = studentsReducer(state.students, currentId);
return {
...result,
[currentSchool.schoolName]: {
...result[currentSchool],
numOfTeachers,
numOfStudents
}
}
}, {});
console.log(resultData);
You can wrap the methods with reselect but keep in mind it will only cache the last input parameter.
Upvotes: 3