r/reactjs 17h ago

What would make a component unmount on some parent renders but not others when the key isn't changing?

I've got a filter panel in a Vite app on React 18 where the date inputs wipe themselves maybe one time in five when the parent list refetches. I've ruled out the usual cause, the child isn't declared inside the parent's render body, and the key I pass it is a stable string. I put a log in the child's mount effect and it fires every time the fields clear, so it's actually remounting rather than losing state some other way. I've been on this about three hours and I can't work out what's different about the renders where it happens.

3 Upvotes

7 comments sorted by

1

u/frogic 15h ago

What does react dev tools say?

1

u/Remarkable-Treat-139 15h ago

Check if a parent component returns null or a different element type during those specific refetches. React unmounts children when the parent render output changes structure regardless of key stability. Inspect the return statement in every ancestor between the filter panel and the root to find where the tree shape diverges on failing renders

1

u/BoBoBearDev 12h ago

Did the parent unmount? You need the entire chain to not unmount.

And make sure you are not using conditional rendering like those

showTheDiv && <div key="abc" >

1

u/Vincent_CWS 6h ago

key or type difference will unmount not re-rendering

-9

u/Temperature_Majestic 17h ago

The 1 in 5 is the useful clue. That's not random, something specific is true about those refetches. Two things that fit:

Sibling list without stable keys. If the panel sits in the same parent as a {results.map(...)} and those rows use index keys or no keys, a refetch that returns a different row count shifts every positional slot, React ends up diffing your panel against what used to be a row, type mismatch, remount. The 1 in 5 would be the refetches where the count actually changes.

A loading swap above it. {isLoading ? <Skeleton/> : <Panel/>} or {data ? <Panel/> : null} flipping for one frame on the slower refetches unmounts the panel. Cache-hit refetches that never flip the flag wouldn't.

To pin it, put the trace in the cleanup, not the mount: useEffect(() => () => console.trace('panel unmount'), []). The stack shows you which parent re-rendered into a different shape right before it died.

13

u/itzrvyning 16h ago

thank you claude