react-native-web icon indicating copy to clipboard operation
react-native-web copied to clipboard

measureInWindow doesn't work properly for multiple similar mounted components

Open gentlee opened this issue 1 year ago • 2 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the issue

After upgrading from 0.18.4 to 0.19.8 version (and tried other 0.19.x with same result), measureInWindow returns the same result for all similar mounted components.

In out case the modal is rendered in the same position for all dropdowns - at the most top dropdown.

Here on the screenshot the focused combobox was clicked, but modal appeared at the first one.

Screenshot 2023-10-05 at 18 59 13

On 0.18.4 version it works.

Expected behavior

measureInWindow works properly.

Steps to reproduce

Use this code to measure coordinates:

comboboxRef.current?.measureInWindow((x, y, width, height) => {
 ...
})

and mount several similar components at once on the page. The result will be the same for all of them.

Test case

wil provide later if needed

Additional comments

No response

gentlee avatar Oct 05 '23 16:10 gentlee

For now workaround is using html element ref for web, provided by findNodeHandle:

measureComboboxLayout: (
  callback: (x: number, y: number, width: number, height: number) => void
) => {
  if (!comboboxHtmlRef.current) {
    return
  }
  const rect = comboboxHtmlRef.current.getBoundingClientRect()
  callback(rect.left, rect.top, rect.width, rect.height)
}

gentlee avatar Oct 05 '23 19:10 gentlee

This issue is reproducible for the inverted FlatList

You can try the following code. Without inverted, it looks like working but doesn't work with inverted=true

import React from "react";
import { FlatList, Pressable, StyleSheet, Text, View } from "react-native";

const DATA = [
  {
    id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
    title: 'First Item',
  },
  {
    id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
    title: 'Second Item',
  },
];
const Item = ({title}) => {
  const ref = React.useRef(null);
  const [pos, setPos] = React.useState(0);
  const onPress = () => {
    if (ref.current) {
      ref.current.measureInWindow((x,y,w,h) => {
        setPos(y);
      });
    }
  };
  return (
    <Pressable style={styles.item} onPress={onPress} ref={ref}>
      <Text style={styles.title}>{title}: {pos}</Text>
    </Pressable>
  )
};

function App() {
  return (
    <View style={styles.app}>
      <FlatList
        data={DATA}
        renderItem={({item}) => <Item title={item.title} />}
        keyExtractor={item => item.id}
        inverted
      />
    </View>
  );
}

const styles = StyleSheet.create({
  app: {
    marginHorizontal: "auto",
    padding: 16,
    maxWidth: 500
  },
  item: {
    backgroundColor: '#f9c2ff',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
  },
  title: {
    fontSize: 32,
  },
});

export default App;

s-alves10 avatar Nov 24 '23 06:11 s-alves10