React Native应用中选中模态框运动项后生成带属性的新<View>
问题分析与解决方案
错误原因
你遇到的ReferenceError: item is not defined是因为handlePress函数未定义参数,但调用时传入了item,函数内部无法识别该变量。另外,直接把JSX元素存在views状态里并非React的最佳实践,应该存储数据而非UI元素,这样更便于维护和状态管理。
修正思路
- 让选中运动的处理函数接收运动对象作为参数
- 将状态改为存储运动数据数组(包含运动信息、重量、组数等)
- 渲染时遍历数据数组,动态生成对应的UI组件
- 为每个运动项添加重量和组数的输入框,并维护各自的输入状态
完整修正代码
import React, { useState } from 'react'; import { View, ScrollView, Modal, Text, TouchableOpacity, TextInput, StyleSheet } from 'react-native'; import myExerciseList from './ExerciseList'; const exercises = myExerciseList; const ExerciseList = () => { // 存储运动数据,每个项包含运动信息、重量、组数 const [exerciseItems, setExerciseItems] = useState([]); const [modalVisible, setModalVisible] = useState(false); // 接收选中的运动对象,添加到列表中 const handleExerciseSelect = (selectedExercise) => { setExerciseItems([ ...exerciseItems, { id: selectedExercise.id, name: selectedExercise.name, weight: '', sets: '' } ]); setModalVisible(false); }; // 更新单个运动项的重量或组数 const updateItemField = (itemId, field, value) => { setExerciseItems(exerciseItems.map(item => item.id === itemId ? {...item, [field]: value} : item )); }; return ( <View style={styles.container}> {/* 渲染所有运动项 */} {exerciseItems.map(item => ( <View key={item.id} style={styles.exerciseBox}> <Text style={styles.exerciseName}>{item.name}</Text> <View style={styles.inputRow}> <TextInput style={styles.input} placeholder="重量" keyboardType="numeric" value={item.weight} onChangeText={(val) => updateItemField(item.id, 'weight', val)} /> <TextInput style={styles.input} placeholder="组数" keyboardType="numeric" value={item.sets} onChangeText={(val) => updateItemField(item.id, 'sets', val)} /> </View> </View> ))} {/* 打开选择模态框 */} <TouchableOpacity style={styles.addButton} onPress={() => setModalVisible(true)} > <Text style={styles.addButtonText}>选择运动</Text> </TouchableOpacity> {/* 运动选择模态框 */} <Modal visible={modalVisible} animationType="slide"> <View style={styles.modalContainer}> <ScrollView style={styles.modalScroll}> {exercises.map((exercise) => ( <TouchableOpacity key={exercise.id} style={styles.modalItem} onPress={() => handleExerciseSelect(exercise)} > <Text>{exercise.name}</Text> </TouchableOpacity> ))} </ScrollView> <TouchableOpacity style={styles.cancelButton} onPress={() => setModalVisible(false)} > <Text>取消</Text> </TouchableOpacity> </View> </Modal> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 16, }, exerciseBox: { borderWidth: 2, borderRadius: 8, padding: 12, marginBottom: 12, backgroundColor: '#fff', }, exerciseName: { fontSize: 16, fontWeight: 'bold', marginBottom: 8, }, inputRow: { flexDirection: 'row', gap: 12, }, input: { flex: 1, borderWidth: 1, borderRadius: 4, padding: 8, }, addButton: { backgroundColor: '#2196F3', padding: 12, borderRadius: 8, alignItems: 'center', }, addButtonText: { color: '#fff', fontSize: 16, fontWeight: 'bold', }, modalContainer: { flex: 1, padding: 16, }, modalScroll: { flex: 1, }, modalItem: { padding: 12, borderBottomWidth: 1, borderBottomColor: '#eee', }, cancelButton: { marginTop: 16, padding: 12, backgroundColor: '#f44336', borderRadius: 8, alignItems: 'center', }, }); export default ExerciseList;
关键修改说明
- 将原
views状态改为exerciseItems,存储运动数据而非JSX元素,符合React状态管理的最佳实践 handleExerciseSelect接收选中的运动对象,初始化重量和组数为空字符串updateItemField通过map方法精准修改单个运动项的重量或组数值- 渲染时遍历
exerciseItems数组,动态生成带输入框的运动项组件 - 优化了样式结构,提升界面易用性和美观度
内容的提问来源于stack exchange,提问作者Diego Guardiola
相关产品推荐
相关产品推荐

