简体   繁体   English

React memoized 组件重新渲染而不改变道具

[英]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())

quoted from the docs引用自文档

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM