Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better solution to open the Menu when 3 dots are clicked in React Native

Tags:

react-native

I am able to open menu when 3 dots icon is clicked for each item. But can the code be written in a better way..

Right now menu is getting created for each card item but ideally it would have been good to create single Menu View and dynamically associate it to some card where ever the 3 dots is clicked.

Expo Source Code Link

Code

export default class App extends React.Component {

  constructor(props, ctx) {
    super(props, ctx);
    this.state = {
      list: [
        { name: "Michael", mobile: "9292929292", ref: React.createRef() },
        { name: "Mason Laon Roah", mobile: "1232313233", ref: React.createRef() },
        { name: "Constructor", mobile: "4949494949", ref: React.createRef() },
        { name: "Rosling", mobile: "4874124584", ref: React.createRef() }
      ],
    };
  }

  _menu = null;

  hideMenu = () => {
    this._menu.hide();
  };

  showMenu = (ref) => {
    this._menu = ref;
    this._menu.show();
  };

  render() {
    const renderItem = ({ item, index }) => (
      <ListItem
          title={
            <View>
              <Text style={{ fontWeight: "bold" }}>{item.name}</Text>
              <Text>{item.mobile}</Text>
            </View>
          }
          subtitle={
            <View>
              <Text>445 Mount Eden Road, Mount Eden, Auckland. </Text>
              <Text>Contact No: 134695584</Text>
            </View>
          }
          leftAvatar={{ title: 'MD' }}
          rightContentContainerStyle={{ alignSelf: 'flex-start'}}
          rightTitle={this.getMenuView(item.ref)}
        />
    );

    return (
      <View style={styles.container}>
        <View style={{ flex: 1, marginTop: 30 }}>
          <FlatList
            showsVerticalScrollIndicator={false}
            keyExtractor={(item, index) => index.toString()}
            data={this.state.list || null}
            renderItem={renderItem}
            ItemSeparatorComponent={() => (
              <View style={{ marginBottom: 5 }} />
            )}
          />
        </View>
      </View>     
    );
  }

  getMenuView(ref) {
    return (
      <Menu
          ref={ref}
          button={<Icon onPress={() => this.showMenu(ref.current)} type="material" color="red" name="more-vert" />}
        >
          <MenuItem onPress={this.hideMenu}>Menu item 1</MenuItem>
          <MenuItem onPress={this.hideMenu}>Menu item 2</MenuItem>
          <MenuItem onPress={this.hideMenu} disabled>
            Menu item 3
          </MenuItem>
          <MenuDivider />
          <MenuItem onPress={this.hideMenu}>Menu item 4</MenuItem>
      </Menu>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
});

Sample Output

like image 468
Sharath Avatar asked Dec 06 '25 05:12

Sharath


1 Answers

As mentioned here, you can find an undocumented UIManager.java class that allows you to create Popups with its showPopupMenu method.

This currently works only for Android.

import React, { Component } from 'react'
import { View, UIManager, findNodeHandle, TouchableOpacity } from 'react-native'
import Icon from 'react-native-vector-icons/MaterialIcons'

const ICON_SIZE = 24

export default class PopupMenu extends Component {
  constructor (props) {
    super(props)
    this.state = {
      icon: null
    }
  }

  onError () {
    console.log('Popup Error')
  }

  onPress = () => {
    if (this.state.icon) {
      UIManager.showPopupMenu(
        findNodeHandle(this.state.icon),
        this.props.actions,
        this.onError,
        this.props.onPress
      )
    }
  }

  render () {
    return (
      <View>
        <TouchableOpacity onPress={this.onPress}>
          <Icon
            name='more-vert'
            size={ICON_SIZE}
            color={'grey'}
            ref={this.onRef} />
        </TouchableOpacity>
      </View>
    )
  }

  onRef = icon => {
    if (!this.state.icon) {
      this.setState({icon})
    }
  }
}

Then use it as follows.

render () {
    return (
      <View>
        <PopupMenu actions={['Edit', 'Remove']} onPress={this.onPopupEvent} />
      </View>
    )
  }

onPopupEvent = (eventName, index) => {
    if (eventName !== 'itemSelected') return
    if (index === 0) this.onEdit()
    else this.onRemove()
}

Source: https://cmichel.io/how-to-create-a-more-popup-menu-in-react-native

like image 70
Pavindu Avatar answered Dec 08 '25 22:12

Pavindu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!