necolas / react-native-web

Cross-platform React UI packages
https://necolas.github.io/react-native-web
MIT License
21.67k stars 1.79k forks source link

onLayout does not fire when only View position changes even when including ResizeObserver polyfill #1525

Closed david-arteaga closed 3 years ago

david-arteaga commented 4 years ago

The problem

The onLayout callback is not being fired when Views change position even when including the ResizeObserver polyfill. (It does not fire on any of the react-native components that have the onLayout callback, like TouchableOpacity)

onLayout does fire on mobile when any View changes position. This leads to some bugs in code that relies on onLayout to calculate the position of Views.

How to reproduce

Simplified test case: https://codesandbox.io/s/stoic-shadow-s63yu (I included resize-observer-polyfill in the Codesanbox example already)

Steps to reproduce:

  1. Render a list of views with the onLayout callback.
  2. Make the view change position (ex: delete one of the views in the list)
  3. The onLayout callback is not fired.

Expected behavior

The onLayout callback should be fired when a View position changes.

Here is a snack with the same code that works without issues on mobile https://snack.expo.io/B10o8NwZI

Environment (include versions). Did this work in previous versions?

Additional context

I came across this bug when trying out react-native-easy-dnd on the web. Everything worked correctly until the View moved from it's original position on the screen. Debugging the code I realized it was because onLayout is not being fired when Views move.

necolas commented 4 years ago

If the browser doesn't trigger the resize observer there's probably not much i can do about it

david-arteaga commented 4 years ago

Is there any other web API that comes to mind that could be used to observe when a DOM element changes position? I found MutationObserver after a quick Google search but it does not seem to fire when the DOM element position changes.

wangjiafenghw commented 4 years ago

can i trigger _handleLayout of All children Component when it's parent Component update\didmount or send a message to all component have onLayout property to calculate a new layoutRes and if different to trigger onLayout Callback when anyone Component update\didmount

necolas commented 3 years ago

I'm going to close this because a) the web API doesn't respond to position changes, b) we've got several cases in React Native where we want onLayout to behave the same as web since it is a perf issue to be firing onLayout when position changes in animations or scroll views.