React Native:FlatList为所有项目而不是选定项目打开模式

Posted

技术标签:

【中文标题】React Native:FlatList为所有项目而不是选定项目打开模式【英文标题】:React Native: FlatList Opens Modal for all Items Instead of Selected Item 【发布时间】:2020-12-10 12:27:20 【问题描述】:

我正在使用React Native FlatList 和React Native Modal。

单击 FlatList 中的项目后,我只想查看 1 个 Modal(包含所选项目的详细信息)。

但是,如果 FlatList 中有 4 个项目,则选择 1 个项目会导致 弹出所有 4 种模式。

无论如何我只能为 FlatList 中的 1 个选定项目显示 1 个模态而不是多个模态?

下面的代码片段(一些代码行已被删除,因为它不需要):

    constructor(props) 
            super(props);
            this.state = 
                dataSource: [],
                isLoading: true,
                modalVisible: false,
            
        
    
    setModalVisible = (visible) => 
            this.setState( modalVisible: visible );
         
        
    
        viewModal(item, price) 
            const  modalVisible  = this.state;
            return (
                <Modal
                    statusBarTranslucent=true
                    animationType="slide"
                    transparent=true
                    visible=modalVisible
                    onRequestClose=() => 
                        Alert.alert("Modal has been closed.");
                    
                >
                    <View>
                        <View>
                            <View>
                                <Text>
                                    Appointment Start Time:
                                </Text>
                                <Text>
                                    moment(item.time_start).format('h:mm a')
                                </Text>
                            </View>
    
                            <View>
                                <Text>
                                    Appointment End Time:
                                </Text>
                                <Text>
                                    moment(item.end_start).format('h:mm a')
                                </Text>
                            </View>
    
                            
    
                            
                            <View style=styles.row>
                                <Text>
                                    Total:
                                </Text>
                                <Text>
                                    price
                                </Text>
                            </View>
                            
                            <View>
                                <View>
                                    <Button
                                        mode="outlined"
                                        onPress=() => 
                                            this.setModalVisible(!modalVisible);
                                        
                                    >
                                        'Cancel'
                                    </Button>
                                </View>
                                
                                <View>
                                    <Button
                                        mode="contained"
                                        onPress=() => 
                                            this.setModalVisible(!modalVisible);
                                        
                                    >
                                        'Accept'
                                    </Button>
                                </View>
                            </View>
                        </View>
                    </View>
                </Modal>
            );
        
    
        viewFreelancerTime() 
            return (
                <View>
                    <FlatList
                        renderItem=( item ) => 
                            let totalPrice = (parseFloat(item.service_price) + parseFloat(item.service_deposit)).toFixed(2);
                            return (
                                <Container>
                                    this.viewModal(item, totalPrice)
                                    <TouchableNativeFeedback
                                        onPress=() => 
                                            this.setModalVisible(true);
                                        
                                    >
                                        <View>
                                            <View>
                                                <Text>
                                                    moment(item.time_start).format('h:mm a')
                                                </Text>
                                            </View>
    
                                            <View>
                                                <Text>
                                                    totalPrice
                                                </Text>
                                            </View>
                                        </View>
                                    </TouchableNativeFeedback>
                                </Container>
                            );
                        
                    />
                </View>
            );
        

render() 
            return (
                <>
                    <View style= flex: 1 >
                        this.viewFreelancerTime()
                    </View>

                </>
            );
    ;

【问题讨论】:

【参考方案1】:

问题是你在renderItem方法中渲染了modal,所以每次选择一个item时,modal会在每个渲染的item中打开。

为了解决这个问题,您必须在 FlatList 的同一级别渲染一个具有绝对位置的自定义 Modal 组件,并将所选项目信息作为道具传递。

更新

就像这样:

import React, useState from "react";
import  Modal  from "react-native";

export default function MyFlatList(props) 
  const [selectedItem, setSelectedItem] = useState(null);

  const handleOnSelectItem = (item) => 
    setSelectedItem(item);
  ;

  const handleOnCloseModal = () => 
    setSelectedItem(null);
  ;

  renderItem = ( item ) => 
    return (
      <Container>
        <TouchableNativeFeedback onPress=() => handleOnSelectItem(item)>
          <View>
            <View>
              <Text>moment(item.time_start).format("h:mm a")</Text>
            </View>

            <View>
              <Text>totalPrice</Text>
            </View>
          </View>
        </TouchableNativeFeedback>
      </Container>
    );
  ;

  return (
    <View>
      <FlatList renderItem=this.renderItem />
      <CustomModal isVisible=selectedItem selectedItem=selectedItem onClose=handleOnCloseModal />
    </View>
  );


export function CustomModal(props) 
  const  isVisible, item, onClose,  /*...*/  = props;

  // Play with the item data
  let totalPrice = (
    parseFloat(item.servicePrice) + parseFloat(item.serviceDeposit)
  ).toFixed(2);

  return <Modal visible=isVisible onRequestClose=onClose>/*...*/</Modal>; // Render things inside the data

如果您要实现无限滚动,我建议您进行分页并使用 FlatList 原生道具。

Pd:为了减少由于状态更新而导致的重新渲染,我正在重用 selectedItem 状态,所以如果它不为空,那么模态将可见

【讨论】:

Monlina 谢谢你的建议。你碰巧有什么例子吗?总的来说,我对 Modal 和 React Native 还很陌生。 我已经更新了答案。我没有尝试过代码,我很快就完成了,但类似。

以上是关于React Native:FlatList为所有项目而不是选定项目打开模式的主要内容,如果未能解决你的问题,请参考以下文章

React Native FlatList 最后一项可见性问题

React Native:如何正确地将 renderItem 项传递给 FlatList,以便它们可以在另一个组件中呈现?

React Native Flatlist不会在PureComponent上重新渲染

React Native FlatList 没有滚动到结束

React Native Flatlist 只渲染一行

React-native flatlist 在 isLoading 上的组件之间共享道具