You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native多组件同名函数问题:react-native-material-menu弹窗异常

解决react-native-material-menu在FlatList多场景下的复用问题

嘿,我一眼就看出问题所在了——你现在所有的Menu组件都共用了同一个_menu引用!FlatList在渲染每一条列表项时,setMenuRef都会把当前Menu的ref覆盖掉this._menu,到最后不管你点哪个菜单按钮,实际操作的都是最后渲染出来的那一个Menu实例,这就是为什么所有按钮都触发同一行为、打开同一个菜单的原因。

下面给你一套适配类组件的修复方案,分步骤来:

1. 重构ref存储方式

把原来单个的_menu变量改成一个对象,用来存储每个列表项对应的Menu ref,用item的唯一ID作为key:

// 替换原来的 _menu = null;
_menus = {};

2. 修改ref赋值函数

让setMenuRef变成一个高阶函数,接收item的ID作为参数,返回一个真正的ref赋值函数,这样就能把每个Menu的ref对应到具体的item上:

setMenuRef = (itemID) => ref => {
  this._menus[itemID] = ref;
};

3. 更新菜单显示/隐藏方法

让这两个方法也接收itemID参数,这样就能精准操作对应item的Menu:

hideMenu = (itemID) => {
  // 可选链操作符防止找不到对应ref时报错
  this._menus[itemID]?.hide();
};

showMenu = (itemID) => {
  this._menus[itemID]?.show();
};

4. 调整FlatList里的Menu组件

把item的ID传递给ref、按钮的点击事件,还有每个MenuItem的点击事件:

<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(item.ID)} 
                  button={ 
                    <Icon 
                      type="Feather" 
                      name="more-vertical" 
                      onPress={() => this.showMenu(item.ID)} 
                      style={{fontSize:20,color:'#555'}} 
                    />
                  }>
                  <MenuItem onPress={() => this.hideMenu(item.ID)}>View</MenuItem>
                  <MenuItem onPress={() => {
                    this.hideMenu(item.ID);
                    // 这里可以添加Edit的具体逻辑,比如传入当前item
                    this.handleEdit(item);
                  }}>Edit</MenuItem>
                  <MenuItem onPress={() => {
                    this.hideMenu(item.ID);
                    this.handleDelete(item.ID);
                  }}>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} 
/>

额外优化:清理refs防止内存泄漏

在组件卸载时清空_menus对象,避免不必要的内存占用:

componentWillUnmount() {
  this._menus = {};
}

这样修改后,每个列表项的Menu都有了独立的引用,点击对应按钮只会触发当前item的菜单操作,不会再出现所有菜单共用一个实例的问题啦。

内容的提问来源于stack exchange,提问作者Zain Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 08:57:39