[英]React memoized component rerenders without props change
I have trouble with memoizing my component.我无法记住我的组件。
const Miscellaneous = () => {
const dispatch = useDispatch<DispFn>();
const brokers = useSelector(getSettingsMiscBrokers);
const charterers = useSelector(getSettingsMiscCharterers);
if (window.charterers) {
console.log(window.charterers === charterers, 'check equality charterers');
} else {
window.charterers = charterers;
}
useEffect(() => {
dispatch(fetchBrokersList());
}, []);
return (
<AclShowSectionWrapper sectionName={CHARTER_SETTINGS}>
<div className="fb" style={{ padding: '1rem 2rem 2rem 2rem' }}>
<Row className="bigHorizontalScroll" grow noWrap>
<Col {...colGrid}>
<Charterers charterers={charterers} />
</Col>
<Col {...colGrid}>
<Brokers brokers={brokers} />
</Col>
</Row>
</div>
</AclShowSectionWrapper>
);
};
export const Charterers = React.memo((props: IProps) => {
console.log('charterers');
return (
<div>{*some stuff here*}</div>
);
});
An this is the selector function for charterers这是承租人的选择器功能
export const getSettingsMiscCharterers = createSelector(
[(state: AppState) => state.shared.data.charterers],
charterers => {
if (!charterers || !charterers.payload) {
return {
...charterers,
payload: [],
status: FETCH_STATUS.inProgress
};
}
return charterers;
}
);
So the problem is, that when I make a change in brokers table and that causes store changes only in brokers part, and this statement console.log(window.charterers === charterers, 'check equality charterers');所以问题是,当我在 brokers 表中进行更改并导致仅在 brokers 部分中的存储更改时,此语句console.log(window.charterers === Charterers, 'check equal Charterers'); always is true, charterers get rendered every time.总是如此,承租人每次都得到回报。
Maybe I am missing something important here?也许我在这里遗漏了一些重要的东西?
This is because you don't provide any function to test on the props equality;这是因为你没有提供任何函数来测试 props 的相等性; so the shallow
comparison is executed.所以执行shallow
比较。
Thus, if your selector
returns a new array/object (I presume it's the case especially if you are using array/object destructing to populate the selectors return value);因此,如果您的selector
返回一个新的数组/对象(我认为是这种情况,尤其是当您使用数组/对象析构来填充选择器返回值时); the shallow equality will always return false;浅等式总是返回 false; and then the component will re-render.然后组件将重新渲染。
I recommend using isEqual
from lodash
to test on the equality我建议使用lodash
isEqual
来测试相等性
import { isEqual } from 'lodash';
Const MemoizedComponent = React.memo(Component, isEqual);
edit :编辑:
You are using the selector like this: useSelector(selectorCreator)
.您正在使用这样的选择器: useSelector(selectorCreator)
。
It should be useSelector(selectorCreator())
它应该是useSelector(selectorCreator())
When using useSelector with an inline selector as shown above, a new instance of the selector is created whenever the component is rendered.当使用 useSelector 和上面显示的内联选择器时,每当渲染组件时都会创建一个选择器的新实例。
Besides, createSelector
calls createSelectorCreator
with the selector;此外, createSelector
使用选择器调用createSelectorCreator
; that, returns a new function each time, that, also, calls the function with a new function every time每次都返回一个新函数,也就是每次都用一个新函数调用该函数
export const createSelector = /* #__PURE__ */ createSelectorCreator(defaultMemoize)
export function createSelectorCreator(memoize, ...memoizeOptions) {
return (...funcs) => {
let recomputations = 0
const resultFunc = funcs.pop()
const dependencies = getDependencies(funcs)
const memoizedResultFunc = memoize(
function () {
recomputations++
// apply arguments instead of spreading for performance.
return resultFunc.apply(null, arguments)
},
...memoizeOptions
)
You can see the concrete implementation in github 具体实现可以在github中查看
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.