React Native中如何将选中的自定义复选框数据传递到下一页?
实现选中复选框名称的跨页面传递
问题描述
我已创建可切换的自定义复选框,并将其与名称一同渲染在FlatList组件中,现在希望通过React Navigation把选中复选框对应的名称传递到下一个页面,该如何实现?
现有代码
自定义复选框组件
import React from "react"; import { TouchableOpacity, View } from "react-native"; import { useState } from "react"; import IconAntDesign from "react-native-vector-icons/AntDesign"; export function CheckBoxCustom() { const [count, setCount] = useState(0); return ( <View> <TouchableOpacity style={{ backgroundColor: "white", width: 20, height: 20, borderWidth: 2, borderColor: "#ddd", }} onPress={() => setCount(!count)} > {count ? ( <IconAntDesign name="check" size={15} color="black" /> ) : null} </TouchableOpacity> </View> ); }
FlatList所在页面
import React, {useState} from 'react'; import { SafeAreaView, Text, View, Image, StyleSheet, FlatList, Dimensions, useWindowDimensions, ScrollView, Button, } from 'react-native'; import Header from '../CustomComponents/RestaurentUI/Header'; import {CheckBoxCustom} from '../CustomComponents/RestaurentUI/Checkbox'; import {TabView, SceneMap, TabBar} from 'react-native-tab-view'; import {useNavigation} from '@react-navigation/native'; import GetCheckBoxData from './GetCheckBoxData'; const data = [ {name: 'Lumlère brûlée', status: 'Problems'}, {name: 'Aucune eau chaude', status: 'Problems'}, {name: 'Lumlère brûlée', status: 'Problems'}, {name: 'Service de ménage', status: 'Problems'}, {name: 'AC non-fonctionnel', status: 'Problems'}, {name: 'WIFI non-fonctionnel', status: 'Problems'}, {name: 'Four non-fonctionnel', status: 'Problems'}, ]; const renderItem = ({item, index}) => { return ( <View> <View style={{flexDirection: 'row'}}> <CheckBoxCustom /> <Text style={{marginLeft: 10}}>{item.name} </Text> </View> </View> ); }; const separator = () => { return ( <View style={{ height: 1, backgroundColor: '#f1f1f1', marginBottom: 12, marginTop: 12, }} /> ); }; const FirstRoute = () => ( <FlatList style={{marginTop: 20}} data={data} keyExtractor={(e, i) => i.toString()} renderItem={renderItem} ItemSeparatorComponent={separator} /> ); const SecondRoute = () => ( <View style={[styles.scene, {backgroundColor: 'white'}]} /> ); const initialLayout = {width: Dimensions.get('window').width}; const renderScene = SceneMap({ first: FirstRoute, second: SecondRoute, }); const ReportScreen = ({navigation}) => { const nav = useNavigation(); const layout = useWindowDimensions(); const [index, setIndex] = useState(0); const [routes] = useState([ {key: 'first', title: 'Problemes'}, {key: 'second', title: 'Besoins complémentaitaires'}, ]); const goToScreen = () => { navigation.navigate('GetCheckBoxData', {title: 'Hii all'}); }; const [checked, setChecked] = useState({}); const checkToggle = id => { setChecked(checked => ({ ...checked, [id]: !checked[id], })); }; return ( <SafeAreaView style={styles.safearea}> <Header title="Report" /> <ScrollView showsVerticalScrollIndicator={false} bounces={false}> <View style={{flexDirection: 'row', marginTop: 20}}> <View style={{flex: 1, height: 1, backgroundColor: '#ccc'}} /> </View> <View style={styles.cardView}> <View style={styles.subView}> <Image style={styles.image} source={require('../Assets/UIPracticeImage/H1.jpg')} /> <View style={styles.internalSubView}> <View style={styles.nameView}> <Text style={styles.nameText}>Pine Hill Green Caban</Text> </View> <View style={styles.dateView}> <Text style={styles.dateText}>May 22-27</Text> </View> </View> </View> </View> <View style={{flexDirection: 'row'}}> <View style={{flex: 1, height: 1, backgroundColor: '#ccc'}} /> </View> <View style={{flex: 1, height: 385, width: '100%'}}> <TabView navigationState={{index, routes}} renderScene={renderScene} onIndexChange={setIndex} initialLayout={initialLayout} style={styles.container} renderTabBar={props => ( <TabBar tabStyle={{alignItems: 'flex-start', width: 'auto'}} {...props} renderLabel={({route, color}) => ( <Text style={{color: 'black'}}>{route.title}</Text> )} style={{backgroundColor: 'white'}} /> )} /> </View> <Button title="Click me" onPress={goToScreen} /> </ScrollView> </SafeAreaView> ); }; export default ReportScreen; const styles = StyleSheet.create({ safearea: {marginHorizontal: 20}, cardView: {borderRadius: 10, marginVertical: 10, paddingVertical: 8}, subView: {flexDirection: 'row'}, image: {height: 80, width: 110, borderRadius: 10}, internalSubView: {justifyContent: 'space-between', flex: 1}, nameView: {justifyContent: 'space-between', flexDirection: 'row', alignItems: 'center', marginLeft: 10}, nameText: {fontWeight: 'bold', width: '45%', fontSize: 15}, dateView: {flexDirection: 'row', alignItems: 'center', marginLeft: 10, justifyContent: 'space-between'}, dateText: {width: 80}, container: {marginTop: 20}, scene: {flex: 1}, });
解决方案
核心思路是将复选框的状态提升到父组件统一管理,再在跳转时筛选选中项并传递,具体步骤如下:
1. 修改自定义复选框组件
移除组件内部的状态,改为接收外部传入的选中状态和点击回调:
import React from "react"; import { TouchableOpacity, View } from "react-native"; import IconAntDesign from "react-native-vector-icons/AntDesign"; export function CheckBoxCustom({ isChecked, onToggle }) { return ( <View> <TouchableOpacity style={{ backgroundColor: "white", width: 20, height: 20, borderWidth: 2, borderColor: "#ddd", justifyContent: "center", alignItems: "center" }} onPress={onToggle} > {isChecked ? ( <IconAntDesign name="check" size={15} color="black" /> ) : null} </TouchableOpacity> </View> ); }
2. 传递状态到FlatList列表项
调整FirstRoute为接收props的函数,将父组件的选中状态和回调传递给每个复选框:
// 修改FirstRoute,接收父组件状态和回调 const FirstRoute = ({ checked, checkToggle }) => ( <FlatList style={{ marginTop: 20 }} data={data} keyExtractor={(e, i) => i.toString()} renderItem={({ item, index }) => ( <View style={{flexDirection: 'row', alignItems: 'center'}}> <CheckBoxCustom isChecked={checked[index] || false} onToggle={() => checkToggle(index)} /> <Text style={{marginLeft: 10}}>{item.name} </Text> </View> )} ItemSeparatorComponent={separator} /> ); // 修改renderScene,传递父组件的状态和回调 const renderScene = SceneMap({ first: (props) => <FirstRoute {...props} checked={checked} checkToggle={checkToggle} />, second: SecondRoute, });
3. 筛选选中名称并传递到下一页
修改goToScreen函数,先筛选选中项的名称,再通过navigation传递:
const goToScreen = () => { // 筛选所有选中项的名称 const selectedNames = data.filter((_, index) => checked[index]).map(item => item.name); // 传递到目标页面 navigation.navigate('GetCheckBoxData', { selectedNames }); };
4. 目标页面接收数据
在GetCheckBoxData页面中,通过route.params获取传递的选中名称:
// GetCheckBoxData.js示例代码 import React from 'react'; import { View, Text, SafeAreaView } from 'react-native'; const GetCheckBoxData = ({ route }) => { const { selectedNames } = route.params; return ( <SafeAreaView style={{flex:1, padding:20}}> <Text style={{fontSize:16, fontWeight:'bold', marginBottom:10}}>选中的问题:</Text> {selectedNames.map((name, index) => ( <Text key={index} style={{marginVertical:4}}>- {name}</Text> ))} </SafeAreaView> ); }; export default GetCheckBoxData;
关键说明
- 状态提升:将复选框状态从组件内部移到父组件,便于统一管理所有选中状态,后续筛选和传递更便捷。
- 标识稳定性:示例中用列表项的
index作为选中状态的key,若数据可能动态变化,建议给data数组添加唯一id字段替代index。 - 导航传参:React Navigation通过
navigation.navigate的第二个参数传递数据,目标页面通过route.params接收。
内容的提问来源于stack exchange,提问作者Dhyana Dave
相关产品推荐
相关产品推荐

