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.
CodePudding user response:
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.