react-resize-detector
react-resize-detector copied to clipboard
No measuring on lazy imported component
https://codesandbox.io/s/charming-lewin-6rnvj?file=/src/App.js
React.lazy
automatically forwards refs, so it should be fine to just wrap a component and still get the ref.
However, react-resize-detector
doesn't get the delayed ref, because it isn't present by the time the useEffect
hook is rerun. ref.current
in the useEffect
dependencies doesn't do anything because of the way it's mutated without triggering a rerender.
I've seen other implementations which always return callback refs wrapped around a ref object to work around this.
I suspect this would be the case with any component which doesn't attach the ref straight away.
Hi @lexanth
Thanks for reporting this issue and for providing a code snippet.
Spent some time trying to fix the problem and failed.
The problem is that ref
is undefined during the initial render and then it gets silently assigned a value. The library needs to be notified somehow. Usually it happens through rerender.
btw, we have useEffect
that is listening for ref.currrent
changes, but, for some reason, it doesn't trigger :(
Yeah the useEffect
won't receive the ref.current
change because mutating ref.current
doesn't trigger a rerender (so doesn't trigger the effect again). Basically the issue is that the ref
isn't set by the time the useEffect
runs. By the way, the hooks ESLint plugin warns that ref.current
in the dependencies array doesn't work.
The solution would be to use a callback ref rather than a mutable ref object - then you can trigger the ResizeObserver
creation when the callback is called, rather than depending on the ref's value having been assigned by the time the useEffect
runs. But it's a reasonably big change! An alternative approach would be to put the ref pointer in state rather than useRef
, then updating it would trigger a rerender.
For anyone else finding this (and for ideas on the fix!), these alternatives don't have the same issue (but have different APIs, other trade-offs etc)
- https://github.com/pbr1111/use-resize-observer
- https://github.com/ZeeCoder/use-resize-observer
Related react issue: https://github.com/facebook/react/issues/21903
The current built-in canonical solution to this is callback refs, but it’s a bit awkward that callback refs have a different API from effects.
Just checked. Using a "callback ref" proposed in old PR would still solve the issue. Relates to prev issue You can also still see the bug on the intial render for the delayed component in updated demo (~ I'm still not sure sure this will ever work with the tragetRef arg)
@lexanth Which lib did you end up using? I was curious about "use-resize-observer". It seems to support a "targetRef". (But nope =). Merging callbacks (e.g) looks like a good idea if you need to support a "targetRef")
Closing the issues with no comments in the past year.
To the participants: If you found a workaround or somehow fixed it - let me know. If you ended up using another library - feel free to mention it here