使用重新选择计算状态数据
Computing state data with reselect
我的 React 网络应用程序的 redux 状态分支结构如下:
a: {
daily: {
offers: {
total: 0,
data: []
},
typ: {
total: 0,
data: []
}
},
monthly: {
offers: {
total: 0,
data: []
},
typ: {
total: 0,
data: []
}
}
},
b: same structure, c:same structure and so on
整个状态通过一个动作更新,由不同的函数调用(大约 10 个 运行 异步的函数)每 30 秒获取一次数据并将其作为有效载荷传递(连同关于什么的信息更新,例如 b.daily.offers)。
每次按照 redux 指南调用时,该操作都会创建整个状态树的新副本。
然后我有一个显示数字的组件,作为该州总计的计算(我传递像 ["a"、"b"]、"monthly"、[=23 这样的道具=] 到组件,以检索每月报价总额的总和)
这使用重新选择如下:
import {createSelector} from 'reselect'
const getGroup= (_, props) => {
switch (props.group) {
case "all":
return ["a", "b", "c"];
default:
return props.group;
}
};
const getTimespan = (_, props) => {
switch (props.timespan) {
case "daily":
return ["daily"];
case "monthly":
return ["daily", "monthly"];
}
};
const getPage = (_, props) => props.page;
const getA = (state) => state.a;
const getC = (state) => state.b;
const getB = (state) => state.c;
export const makeGetStatistic = () => {
return createSelector(
[getA, getB, getC, getPage, getGroup, getTimespan],
(a, b, c, page, group, timespan) => {
let o = 0;
let data = {
"a": a,
"b": b,
"c": c
};
group.forEach((device) => {
timespan.forEach((time) => {
o += data[device][time][page].total;
})
})
return {data: o}
});
};
随着后台函数越来越多(而且还会越来越多,因为以后我需要取更多的数据),这些selector被调用的越来越多,webapp越来越有感觉了"slow".
有没有办法优化这个选择器? (还有 actions/state 树?)
我在这里看到的第一个问题是 getGroup
和 getTimespan
总是 return 一个新数组 ,使 makeGetStatistic
无效任何单个调用的选择器缓存。
发生这种情况是因为reselect
缓存在新的和以前传递的值之间执行严格的相等比较(===
)检查,并且JS通过引用比较objects/arrays。
如果你想保留两个 getter return 一个数组,你需要确保它们 return 在使用相同的输入调用时使用相同的数组.类似于:
const ALL_GROUPS = ["a", "b", "c"];
const getGroup= (_, props) => {
switch (props.group) {
case "all":
return ALL_GROUPS;
default:
return props.group;
}
};
const DAILY_TIMESPAN = ["daily"];
const MONTHLY_TIMESPAN = ["daily", "monthly"];
const getTimespan = (_, props) => {
switch (props.timespan) {
case "daily":
return DAILY_TIMESPAN;
case "monthly":
return MONTHLY_TIMESPAN;
}
};
这样 reselect
应该能够在使用相同输入调用时至少提供初始级别的数据记忆。
我的 React 网络应用程序的 redux 状态分支结构如下:
a: {
daily: {
offers: {
total: 0,
data: []
},
typ: {
total: 0,
data: []
}
},
monthly: {
offers: {
total: 0,
data: []
},
typ: {
total: 0,
data: []
}
}
},
b: same structure, c:same structure and so on
整个状态通过一个动作更新,由不同的函数调用(大约 10 个 运行 异步的函数)每 30 秒获取一次数据并将其作为有效载荷传递(连同关于什么的信息更新,例如 b.daily.offers)。 每次按照 redux 指南调用时,该操作都会创建整个状态树的新副本。
然后我有一个显示数字的组件,作为该州总计的计算(我传递像 ["a"、"b"]、"monthly"、[=23 这样的道具=] 到组件,以检索每月报价总额的总和) 这使用重新选择如下:
import {createSelector} from 'reselect'
const getGroup= (_, props) => {
switch (props.group) {
case "all":
return ["a", "b", "c"];
default:
return props.group;
}
};
const getTimespan = (_, props) => {
switch (props.timespan) {
case "daily":
return ["daily"];
case "monthly":
return ["daily", "monthly"];
}
};
const getPage = (_, props) => props.page;
const getA = (state) => state.a;
const getC = (state) => state.b;
const getB = (state) => state.c;
export const makeGetStatistic = () => {
return createSelector(
[getA, getB, getC, getPage, getGroup, getTimespan],
(a, b, c, page, group, timespan) => {
let o = 0;
let data = {
"a": a,
"b": b,
"c": c
};
group.forEach((device) => {
timespan.forEach((time) => {
o += data[device][time][page].total;
})
})
return {data: o}
});
};
随着后台函数越来越多(而且还会越来越多,因为以后我需要取更多的数据),这些selector被调用的越来越多,webapp越来越有感觉了"slow". 有没有办法优化这个选择器? (还有 actions/state 树?)
我在这里看到的第一个问题是 getGroup
和 getTimespan
总是 return 一个新数组 ,使 makeGetStatistic
无效任何单个调用的选择器缓存。
发生这种情况是因为reselect
缓存在新的和以前传递的值之间执行严格的相等比较(===
)检查,并且JS通过引用比较objects/arrays。
如果你想保留两个 getter return 一个数组,你需要确保它们 return 在使用相同的输入调用时使用相同的数组.类似于:
const ALL_GROUPS = ["a", "b", "c"];
const getGroup= (_, props) => {
switch (props.group) {
case "all":
return ALL_GROUPS;
default:
return props.group;
}
};
const DAILY_TIMESPAN = ["daily"];
const MONTHLY_TIMESPAN = ["daily", "monthly"];
const getTimespan = (_, props) => {
switch (props.timespan) {
case "daily":
return DAILY_TIMESPAN;
case "monthly":
return MONTHLY_TIMESPAN;
}
};
这样 reselect
应该能够在使用相同输入调用时至少提供初始级别的数据记忆。