Search code examples
javascriptreact-nativereact-native-paper

Flatlist Item in search results needs to be tapped twice for onPress to register


I have a react native modal with a search bar and a flatlist that shows results. The search result in the flatlist has to be tapped twice for the click to register. I need to figure out how to make it work on first click. Here is the code

const Item = ({ item, onPress, value }) => (
  <TouchableOpacity style={styles.modalItemStyle} onPress={onPress}>
    <View style={styles.modalIconStyle}>
      {item.id === value && <Icon name="sheep" size={20} color="#68c25a" />}
    </View>
    <Text style={styles.modalItemTextStyle}>{item.title}</Text>
  </TouchableOpacity>
);

const MyDropdown = ({
  data,
  label,
  field,
  onSelect,
  value,
  searchable = true,
}) => {
  const [modalOpen, setModalOpen] = useState(false);
  const [selectedValue, setSelectedValue] = useState(value);
  const [query, setQuery] = useState("");
  const [modalData, setModalData] = useState(data);


  useEffect(() => {
    if (query.length > 0) {
      const filteredData = data.filter((item) =>
        item.title.toLowerCase().includes(query.toLowerCase())
      );
      setModalData(filteredData);
    } else {
      setModalData(data);
    }
  }, [query]);

  const inputRef = useRef(null);
  const searchRef = useRef(null);

  const renderItem = ({ item }) => {
    return (
      <Item
        item={item}
        value={selectedValue.id}
        onPress={() => {
          inputRef.current.blur();
          Keyboard.dismiss();
          setQuery("");
          setSelectedValue(item);
          setModalOpen(false);
        }}
      />
    );
  };

  return (
    <View style={styles.selectContainer}>
      <TextInput
        ref={inputRef}
        //react native paper text input with value and label
        label={label}
        value={selectedValue.title}
        style={styles.sheepTextInput}
        mode="outlined"
        onChangeText={(text) => onSelect(text)}
        showSoftInputOnFocus={false}
        onFocus={() => {
          setModalOpen(true);
          inputRef.current.blur();
        }}
      ></TextInput>
      <Modal height="auto" isVisible={modalOpen}>
        <View style={styles.modal}>
          {searchable && (
            <View>
              <TextInput
                ref={searchRef}
                mode="outlined"
                outlineColor="#68c25a"
                activeOutlineColor="#68c25a"
                style={styles.modalSearch}
                value={query}
                onChangeText={(q) => setQuery(q)}
                placeholder="Search"
                //add clear button
                right={
                  <TextInput.Icon
                    name="close"
                    color="#68c25a"
                    onPress={() => {
                      setQuery("");
                    }}
                  />
                }
              ></TextInput>
            </View>
          )}
          <FlatList
            keyboardShouldPersistTaps="always"
            data={modalData}
            renderItem={renderItem}
            keyExtractor={(item) => item.id}
          />
        </View>
      </Modal>
    </View>
  );
};

I tried adding keyboardShouldPersistTaps with different options to flatlist, I also tried to blur through refs (searchref), but none of those approaches worked. What am I doing wrong?


Solution

  • I managed to fix this by setting the keyboardshouldpersisttaps property to handled on every scrollview, including the flatlist in question and the component that renders all of those inputs in my form. I also had to wrap the flatlist with the search input in a scrollview. Of course I now have a virtualized lists should never be nested warning, but at least the taps now work.