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

React Native应用中选中模态框运动项后生成带属性的新<View>

问题分析与解决方案

错误原因

你遇到的ReferenceError: item is not defined是因为handlePress函数未定义参数,但调用时传入了item,函数内部无法识别该变量。另外,直接把JSX元素存在views状态里并非React的最佳实践,应该存储数据而非UI元素,这样更便于维护和状态管理。

修正思路

  1. 让选中运动的处理函数接收运动对象作为参数
  2. 将状态改为存储运动数据数组(包含运动信息、重量、组数等)
  3. 渲染时遍历数据数组,动态生成对应的UI组件
  4. 为每个运动项添加重量和组数的输入框,并维护各自的输入状态

完整修正代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:52:39