我的一个组件正在重新渲染,我意识到这是因为下面的allPageViews选择器:
const getPages = (state: IAppState) => {
return state.pages;
};
export const attachPageViews = createSelector(
getPages,
(pages) => pages.pageViews
);
export const selectPageViews = createSelector(
attachPageViews,
(pageViews) => pageViews
);
export const allPageViews = createSelector(
selectPageViews,
(pageStore: PageViewStore) => {
let returnedPageViews: PageView[] = [];
for (const section of Object.values(pageStore.sections)) {
for (const page of Object.values(section!.pageViews)) {
returnedPageViews = [...returnedPageViews, page!];
}
}
return returnedPageViews;
}
);
当我调度一个动作时,我在更改页面缩减器,但不更改其中包含的pageViews(页面具有另一个称为数据的键,我正在更新)。因此,根据我的理解,selectPageViews不应更改(因为基础的pageViews不会更改),因此allPageViews应该只是存储而不是重新计算,因为没有任何更新。
尽管如此,它仍在重新计算。当我将returnPageViews数组和for循环移到使用useSelector()的组件中时,该组件停止了重新渲染。
所以我的问题是-重新选择是如何工作的,为什么要在allPageViews中创建数组时重新选择并触发重新渲染?
答案 0 :(得分:0)
我正在更改页面精简器,但没有更改其中包含的pageViews(页面有另一个名为我正在更新的数据的键)。因此,根据我的理解,selectPageViews不应更改(因为基础的pageViews不会更改),因此allPageViews应该只是记录性的,而不是因为没有任何更新而重新计算。
没错,state.page.pageViews并未更改,因此selectPageViews
将返回记录的结果,而allPageViews也将返回。
尽管如此,它仍在重新计算。当我将returnPageViews数组和for循环移到使用useSelector()的组件中时,该组件停止了重新呈现。所以我的问题是-当在allPageViews中创建数组时,Reselect如何工作,为什么它会重新计算并触发重新渲染?
那没有意义,所以选择器不是在触发重新渲染吗? Nonetheless it was re-calculating
是不正确的,这是下面的代码,表明您的最初假设是正确的;如果您不更改state.page.pageViews,则selectPageViews和allPageViews都将返回其记忆的结果(不会重新计算):
const { createSelector } = Reselect;
const getPages = (state) => {
return state.pages;
};
const attachPageViews = createSelector(
getPages,
(pages) => pages.pageViews
);
//this one is kind of useless, it does x=>x so you may as
// well do: const selectPageViews = attachPageViews
const selectPageViews = createSelector(
attachPageViews,
(pageViews) => {
console.log(
'selectPageViews logs once but is called twice'
);
return pageViews;
}
);
const allPageViews = createSelector(
selectPageViews,
(pageStore) => {
console.log(
'allPageViews logs once but is called twice'
);
return { new: 'object', pageStore };
}
);
const state = {
pages: {
pageViews: { value: 'this is page views' },
},
};
console.log('calling allPageViews first time');
const one = allPageViews(state);
console.log('calling allPageViews second time with changed state.pages');
const two = allPageViews({
...state,
pages: {
...state.pages,
changedSomething: true,
},
});
console.log('both results are the same:',one === two);
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
<div id="root"></div>
答案 1 :(得分:0)
根据我的经验,当side createSelector中的任何依赖项重新计算时,它将重新渲染,例如
const dep2 = createSelector(
dep4,
dep5,
(a, b) => a * b;
dep1,
dep2,
dep3,
(a, b, c) => d
每当计算d2时,最后一个就会重新计算