3

I have a component defined as

export default function MyComp({
    ...someprops
}) {
    const [data, setData] = useState([]);
    const searchRef = useRef();

    return (
        <Box>
            {!showEmptyState ? (
                <LzSearch
                    onUpdate={(items) => setData(items)}
                    ref={searchRef}
                />
            ) : (
               <Box />
            )}

        </Box>
    );
}

Where as LzSearch is defined as

const LzSearch = forwardRef((props, ref) => {
    const {       
        ...rest
    } = props;
    const classes = useStyles();
    const hashData = {};

    console.log(hashData);

    function updateHashData() {
       // Function is called at some point after getting data from API
       setHashData(...);
       onUpdate(...)
    }

    return (
        <Box>
            {`Some components`}
        </Box>
    );
});

export default memo(LzSearch);

After calling onUpdate(), my main component is updated however it then re-render my LzSearch component and resetting the hashData. I have added memo however its doing the same thing.

How can I avoid re rendering.

Muhammad Umar
  • 11,391
  • 21
  • 91
  • 193

1 Answers1

5

This has nothing to do with the ref. LzSearch is rerendering because the onUpdate prop is changing. MyComp will need to use useCallback to keep the onUpdate function the same between renders:

export default function MyComp({
    ...someprops
}) {
    const [data, setData] = useState([]);
    const searchRef = useRef();

    const onUpdate = useCallback((items) => {
      setData(items);
    }, [])

    return (
        <Box>
            {!showEmptyState ? (
                <LzSearch
                    onUpdate={onUpdate}
                    ref={searchRef}
                />
            ) : (
               <Box />
            )}

        </Box>
    );
}

re-render my LzSearch component and resetting the hashData

Be aware that memo is just meant as a performance optimization tool, not a way to fix bugs. Your component needs to work correctly if it happens to rerender for some reason. memo might stop some renders, but it can't guarantee that the component will never rerender. Examples of things that can cause a rerender even with useMemo include: changing props, changing state, changing context, strict mode's double render feature, concurrent mode aborting and then repeating a portion of the component tree.

Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • I understand re-render can happen however I don't want to re-render just for updating something. Use callback is still not stopping it. I don't want to use ref on "data" – Muhammad Umar Mar 03 '22 at 21:21
  • `Use callback is still not stopping it` are there any other props that you didn't include in your question? I notice you're using `const { ...rest } = props;`, which you wouldn't typically do if there's just one prop. – Nicholas Tower Mar 03 '22 at 21:26