Touchable presses not firing in absolute positioned container with zIndex (for a dropdown)

You have to set position for Select instead of Option

here is a snack: https://snack.expo.io/HkDHHo6YV

change wrap and menu style with given below:

wrap: {
  position: 'absolute',
  zIndex: 10,
  width: "100%",
  backgroundColor: 'rgb(73,75,77)',
},
menu: {
  backgroundColor: 'rgb(73,75,77)',
  maxHeight: 300,
},

Edit, Working solution

The missing piece was to account for the space under the dropdown since it was completely absolutely positioned. I had to change the Select component to render a "padding" element to account for the space.

class Select extends React.PureComponent {
  render() {
    const { value, open, options, onOptionPress } = this.props;
    const shadowStyle = shadowStyles[Platform.OS];
    return (
      <>
        <View style={{height: 60}}></View>
        <View style={[shadowStyle, styles.wrap]}>
          <TouchableWithoutFeedback onPress={this.props.onPress}>
            <View style={styles.selectContainer}>
              <Text>{value}</Text>
            </View>
          </TouchableWithoutFeedback>
          {open && (
            <View style={styles.menu}>
              {options.map((item, idx) => (
                <Option value={item} key={idx} onPress={onOptionPress} />
              ))}
            </View>
          )}
        </View>
      </>
    );
  }
}

Then adjusted the height of the styles.selectContainer to be the same height 60

selectContainer: {
  padding: 16,
  height: 60
},

Full working example

import * as React from 'react';
import {
  Text,
  Button,
  View,
  StyleSheet,
  Platform,
  TouchableWithoutFeedback,
  TouchableOpacity,
} from 'react-native';

class Dropdown extends React.Component {
  constructor() {
    super();
    this.state = {
      open: false,
      selected: undefined,
    };
  }

  handleSelectPress = () => {
    this.setState({ open: !this.state.open });
  };
  handleOptionPress = item => {
    this.setState({ selected: item, open: !this.state.open });
    this.props.onSelectOption(item);
  };
  render() {
    const { selected = {}, open } = this.state;
    const { placeholder = '', options = [] } = this.props;

    return (
      <Select
        onPress={this.handleSelectPress}
        value={selected.name || placeholder}
        open={open}
        options={options}
        onOptionPress={this.handleOptionPress}
      />
    );
  }
}

const shadowStyles = {
  ios: {
    shadowOpacity: 0.3,
    shadowRadius: 3,
    shadowOffset: {
      height: 1,
      width: 1,
    },
  },
  android: {
    elevation: 5,
  },
};

class Select extends React.PureComponent {
  render() {
    const { value, open, options, onOptionPress } = this.props;
    const shadowStyle = shadowStyles[Platform.OS];
    return (
      <>
        <View style={{height: 60}}></View>
        <View style={[shadowStyle, styles.wrap]}>
          <TouchableWithoutFeedback onPress={this.props.onPress}>
            <View style={styles.selectContainer}>
              <Text>{value}</Text>
            </View>
          </TouchableWithoutFeedback>
          {open && (
            <View style={styles.menu}>
              {options.map((item, idx) => (
                <Option value={item} key={idx} onPress={onOptionPress} />
              ))}
            </View>
          )}
        </View>
      </>
    );
  }
}

class Option extends React.PureComponent {
  handlePress = () => {
    this.props.onPress(this.props.value);
  };
  render() {
    const { value } = this.props;
    return (
      <TouchableOpacity onPress={this.handlePress}>
        <View style={styles.optionContainer}>
          <Text>{value.name}</Text>
        </View>
      </TouchableOpacity>
    );
  }
}

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.root}>
        <Dropdown
          placeholder="--- SELECT ---"
          options={[
            { name: 'Press me!', id: '1' },
            { name: 'No Me!', id: '2' },
            { name: 'Cmon guys, here!', id: '3' },
          ]}
          onSelectOption={item => console.log(`item pressed! ${item}`)}
        />
        <Text>hellof</Text>
        <View style={{backgroundColor: "red", height: 250}} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  root: {
    width: 360,
    height: 640,
    backgroundColor: '#292c2e',
    marginTop: 100
  },
  wrap: {
    position: 'absolute',
    zIndex: 10,
    width: "100%",
    backgroundColor: 'rgb(73,75,77)',
  },
  selectContainer: {
    padding: 16,
    height: 60
  },
  menu: {
    backgroundColor: 'rgb(73,75,77)',
    maxHeight: 300,
  },
  optionContainer: {
    padding: 16,
    height: 60
  },
});

There is a problem with your styles in styles.menu not with zIndex.

You have given position:'absolute' and top:'100%'.

This means your child view is positioned as absolute to the parent view and your child view will start right after your parent view is completing because of top:"100%".

Conclusion: your options are rendering out of the parent. yes, they are visible because there are no other components below and more of that zIndex is higher. and you can not touch anything that is not withing the range of parent.

Solution:

See working snack here

in styles.menu, change these,

  menu: {
    backgroundColor: 'rgb(73,75,77)',
    zIndex: 1005,
    top: 0,
    left: 0,
    right: 0,
    maxHeight: 300,
  },

and you can remove zIndex: 1000 and 1005 also :)