React Native:Class组件弹窗选中ID传递至Function组件主页面
解决React Native弹窗组件向主页面传递数据的问题
我是React Native新手,JavaScript经验有限。我的应用里有一个作为弹窗的Class组件,点击TouchableOpacity会弹出菜单。现在已经能获取菜单中被点击按钮的id,但没法把这个id传递回作为主页面的Function组件(也就是触发弹窗的TouchableOpacity所在的页面)。
实现步骤
1. 改造主页面(Function组件)
在主页面中添加状态保存选中的id,并定义回调函数接收弹窗传递的数据:
import { StyleSheet, Text, View, Image,TouchableOpacity} from 'react-native' import React,{useState} from 'react' import tw, { create } from 'twrnc'; import Map from "../components/Map" import { SafeAreaView } from 'react-native-safe-area-context'; import { BottomPopup } from '../components/popup'; import { selectTrucks} from '../slices/navSlice'; import { useSelector } from 'react-redux'; const Logistics = () => { const Trucks = useSelector(selectTrucks); const [selectedTruckId, setSelectedTruckId] = useState(null); // 新增状态存储选中的ID let popupRef = React.createRef() const onShowPopup = () => { popupRef.show() } const onClosePopup = () => { popupRef.close() } // 新增回调函数,接收弹窗传来的ID const handleTruckSelect = (truckId) => { setSelectedTruckId(truckId); console.log("选中的卡车ID:", truckId); onClosePopup(); // 可选:获取ID后自动关闭弹窗 } return ( <View style={{flex:1,resizeMode:'contain'}}> <View style={tw`h-12/16`}> <Map/> </View> <TouchableOpacity onPress={onShowPopup} style={{top:'-68%'}}> <Image source = {{uri: "https://icon-library.com/images/app-menu-icon/app-menu-icon-21.jpg" }} style = {{width:'20%', height:40,resizeMode:'contain'}} /> {/* 实时显示选中的卡车ID */} <Text style={{color:'black',paddingLeft:2,fontSize: 26,fontWeight:"bold",top:-37,left:70}}>Truck {selectedTruckId ? `#${selectedTruckId}` : ''}</Text> </TouchableOpacity> <BottomPopup title = "Select Option" ref = {(target)=> popupRef = target} onTouchOutside={onClosePopup} data={Trucks.TrucksInfo} onItemSelect={handleTruckSelect} // 将回调传递给弹窗组件 /> <SafeAreaView style={{top:'-13%'}}> <Text style={{color:'darkgreen',paddingLeft:2,fontSize: 36,fontWeight:"bold"}}>123 Elmo Street</Text> <Text style={{color:'darkgreen',paddingLeft:2,fontSize: 24,fontWeight:"bold"}}>L4L 6L8, Mississauga, Ontario</Text> <Text style={{color:'darkgreen',paddingLeft:2,fontSize: 18,fontWeight:"bold"}}>Phone Number: 416-749-6857{'\n'}Client: Bobby Jeff{'\n'}Order Number: 7187181{'\n'}Packing Slip Number: 882929</Text> <Text style={{color:'black',fontSize: 18,paddingLeft:2}}>Customer Notified: Yes at 2:32 PM</Text> </SafeAreaView> </View> ) } export default Logistics const styles = StyleSheet.create({})
2. 修改弹窗组件(Class组件)
接收主页面传递的回调函数,在点击菜单按钮时调用该函数并传递ID:
import { Modal,Dimensions,TouchableWithoutFeedback,StyleSheet,View,Text,FlatList,TouchableOpacity} from "react-native"; import React from "react"; import { useNavigation } from '@react-navigation/native'; const deviceHeight = Dimensions.get('window').height export class BottomPopup extends React.Component { constructor(props){ super(props) this.state = { show:false } } show = () => { this.setState({show:true}) } close = () => { this.setState({show:false}) } renderOutsideTouchable(onTouch) { const view = <View style = {{flex:1,width:'100%'}}/> if (!onTouch) return view return ( <TouchableWithoutFeedback onPress={onTouch} style={{flex:1,width:'100%'}}> {view} </TouchableWithoutFeedback> ) } renderTitle = () => { const {title} = this.props return ( <View style={{alignItems:'center'}}> <Text style={{ color:'#182E44', fontSize:25, fontWeight:'500', marginTop:15, marginBottom:30, }}> {title} </Text> </View> ) } renderContent = () => { const {data} = this.props return ( <View> <FlatList style = {{marginBottom:130}} showsVerticalScrollIndicator = {false} data={data} renderItem={this.renderItem} extraData={data} keyExtractor={(item,index)=>index.toString()} ItemSeparatorComponent={this.renderSeparator} contentContainerStyle={{ paddingBottom:40 }} /> </View> ) } renderItem = ({item}) => { return( <TouchableOpacity onPress={() => { this.close(); // 调用主页面传递的回调,把ID传回去 this.props.onItemSelect(item.id); }} > <View style = {{height:50,flex:1,alignItems:'flex-start',justifyContent:'center',marginLeft:20}}> <Text style={{fontSize:18,fontWeight:'normal',color:"#182E44"}}>{item.name}</Text> </View> </TouchableOpacity> ) } renderSeparator = () => { return( <View style={{ opacity:0.1, backgroundColor:'#182E44', height:1 }} /> ) } render() { let {show} = this.state const {onTouchOutside,title} = this.props return ( <Modal animationType={"fade"} transparent={true} visible={show} onRequestClose={this.close} > <View style={{flex:1, backgroundColor:"#000000AA",justifyContent:'flex-end'}}> {this.renderOutsideTouchable(onTouchOutside)} <View style={{ backgroundColor:'#FFFFFF', width:'100%', paddingHorizontal:10, maxHeight:deviceHeight*0.4}} > {this.renderTitle()} {this.renderContent()} </View> </View> </Modal> ) } }
核心逻辑
这是React父子组件通信的基础方式:父组件(主页面)传递一个回调函数给子组件(弹窗),子组件在触发点击事件时调用该回调,并将需要传递的数据作为参数传入,父组件通过接收参数更新自身状态,从而实现数据从子组件到父组件的传递。
内容的提问来源于stack exchange,提问作者RoRoBoat
相关产品推荐
相关产品推荐

