简体   繁体   中英

Multiple Component with Same Function Name in React Native

I'm using react-native-material-menu 's popup for showing menu options.

But the issue is, it's not working for multiple scenarios.

I mean when I click on first menu button, the same methods gets triggered and hence the same menu is opened every time.

What should be the better approach for to handle this particular scenario.

 _menu = null;

 setMenuRef = ref => {
     this._menu = ref;
 };

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

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


  <FlatList
      data={this.state.clientsList}
      renderItem={({ item }) => {
      return (
          <View style={styles.caseItem} >
              <Card style={styles.card}>
                  <CardItem>
                     <Body>
                        <View style={styles.rowTitle}>
                           <Text style={styles.title}>{item.FullName}</Text>
                           <Menu
                                ref={this.setMenuRef}
                                button={
                                   <Icon 
                                        type="Feather" 
                                        name="more-vertical" 
                                        onPress={this.showMenu} 
                                           style{{fontSize:20,color:'#555'}} 
                                     />
                             }>
                                <MenuItem onPress={this.hideMenu}>View</MenuItem>
                                <MenuItem onPress={this.hideMenu}>Edit</MenuItem>
                                <MenuItem onPress={this.hideMenu}>Delete </MenuItem>
                            </Menu>
                        </View>

                        <View>
                            <Text style={styles.lbl}>Email: <Text style={styles.lblValue}>{item.EmailID}</Text></Text>
                            <Text style={styles.lbl}>Client Type: <Text style={styles.lblValue}>{item.ClientType}</Text></Text>
                        </View>
                     </Body>
                  </CardItem>
               </Card>
            </View>
         );
      }}
      keyExtractor={item => item.ID}
   />

Snack Here

To handle the states in the correct way, you will need to create a new Class which will be handling just the MenuItem

The below code will work: Here is the Snack .

import * as React from "react";
import { Text, View, StyleSheet } from "react-native";
import Constants from "expo-constants";
import { Container, Content, Card, CardItem, Body, Icon } from "native-base";
import * as Font from "expo-font";
import Menu, { MenuItem, MenuDivider } from "react-native-material-menu";
// You can import from local files
import AssetExample from "./components/AssetExample";

export default class App extends React.Component {

  onView = () => {
    alert("Do something here");
    console.log("You can do what ever you want here");
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.caseItem}>
          <Card style={styles.card}>
            <CardItem>
              <Body>
                <View style={styles.rowTitle}>
                  <Text style={styles.title}>John Doe</Text>
                  <CustomMenu onView={this.onView}/>
                </View>

                <View>
                  <Text style={styles.lbl}>
                    Email: <Text style={styles.lblValue}>john@yopmail.com</Text>
                  </Text>
                  <Text style={styles.lbl}>
                    Client Type: <Text style={styles.lblValue}>Individual</Text>
                  </Text>
                </View>
              </Body>
            </CardItem>
          </Card>
        </View>
        <View style={styles.caseItem}>
          <Card style={styles.card}>
            <CardItem>
              <Body>
                <View style={styles.rowTitle}>
                  <Text style={styles.title}>John Doe</Text>
                  <CustomMenu  onView={this.onView}/>
                </View>

                <View>
                  <Text style={styles.lbl}>
                    Email: <Text style={styles.lblValue}>john@yopmail.com</Text>
                  </Text>
                  <Text style={styles.lbl}>
                    Client Type: <Text style={styles.lblValue}>Individual</Text>
                  </Text>
                </View>
              </Body>
            </CardItem>
          </Card>
        </View>
        <View style={styles.caseItem}>
          <Card style={styles.card}>
            <CardItem>
              <Body>
                <View style={styles.rowTitle}>
                  <Text style={styles.title}>John Doe</Text>
                  <CustomMenu onView={this.onView} />
                </View>

                <View>
                  <Text style={styles.lbl}>
                    Email: <Text style={styles.lblValue}>john@yopmail.com</Text>
                  </Text>
                  <Text style={styles.lbl}>
                    Client Type: <Text style={styles.lblValue}>Individual</Text>
                  </Text>
                </View>
              </Body>
            </CardItem>
          </Card>
        </View>
      </View>
    );
  }
}

class CustomMenu extends React.Component {
  _menu = null;
  setMenuRef = ref => {
    this._menu = ref;
  };

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

  onViewClick = () => {
    const {onView} = this.props;
    onView();
    this.hideMenu();
  }

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

  render() {
    return (
      <Menu
        ref={this.setMenuRef}
        button={
          <Icon
            type="Feather"
            name="more-vertical"
            onPress={this.showMenu}
            style={{ fontSize: 20, color: "#555" }}
          />
        }
      >
        <MenuItem onPress={this.onViewClick}>View</MenuItem>
        <MenuItem onPress={this.hideMenu}>Edit</MenuItem>
        <MenuItem onPress={this.hideMenu}>Delete </MenuItem>
      </Menu>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    paddingTop: Constants.statusBarHeight,
    backgroundColor: "#ecf0f1",
    padding: 8
  },
  rowTitle: {
    flexDirection: "row",
    justifyContent: "space-between",
    width: "100%"
  },
  title: {
    fontSize: 14,
    marginBottom: 5
  },
  lbl: {
    fontSize: 11,
    color: "#000"
  },
  lblValue: {
    fontSize: 11,
    color: "#555",
    fontWeight: "normal"
  },
  caseItem: {
    marginBottom: 0
  }
});

Since the FlatList will iterate over the menu items, you need to maintain index for each iterable menu options.

You can check, you are passing item object within renderItems prop. So you can use the same item.id as a key to your child (iterable) component.

Since the child component now maintains an index, so now you can pass it in methods which will help you differentiate the event which got triggered from the child element.

I hope this might give you an idea about the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM