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

React Native中动态创建TextInput的实现问题求助

Fixing Dynamic TextInput Handling in Your React Native Todo App

Hey there! Let's get your dynamic TextInput feature working properly. The core issue with your current code is that your input change handler isn't correctly identifying which specific TextInput is being updated, and there are a few state-related bugs throwing things off. Here's how to fix it step by step:

Key Problem to Solve

Your handleformItemsChange function tries to guess which input to update by filtering text content—this is unreliable (e.g., multiple inputs could have empty text or matching characters). Instead, we need to pass the unique id of each todo item directly to the change handler, so we can precisely target the right item in our state array.

Modified Code with Fixes

import React from 'react';
import {StyleSheet, View, Button, TextInput, ScrollView} from 'react-native';
import {Constants} from 'expo';
import FormNewTodo from '../components/FormNewTodo'

const styles = StyleSheet.create ({
  appContainer: {
    flex: 1,
    paddingTop: Constants.statusBarHeight,
    backgroundColor: 'white',
  },
  form: {
    padding: 10,
    borderColor: 'black',
    borderWidth: 1,
  },
})

let id = 0;

export default class AddTodoForm extends React.Component {
  state = {
    titleText: '',
    formItems: [],
  }

  handleAddTodo = () => {
    this.setState({
      formItems: [...this.state.formItems, {id: id++, text: ''},],
    })
  };

  // Updated handler: accepts text AND the item's unique id
  handleformItemsChange = (text, itemId) => {
    // Create a copy of the current formItems array to maintain immutability
    const newArray = [...this.state.formItems];
    // Find the index of the item with the matching id
    const itemIndex = newArray.findIndex(item => item.id === itemId);
    // Update the text for that specific item if found
    if (itemIndex !== -1) {
      newArray[itemIndex] = {...newArray[itemIndex], text};
      // Update state with the modified array
      this.setState({ formItems: newArray });
    }
  }

  handleFormTitleChange = titleText => {
    this.setState({titleText: titleText})
  }

  handleSave = () => {
    this.props.onSubmit(this.state)
    // Reset the global id counter correctly (remove 'let' to target the global variable)
    id = 0;
  };

  static navigationOptions = ({ navigation }) => {
    return {
      headerTitle: 'TO DO´s',
      headerRight: (
        <Button title="Add" onPress={() => navigation.navigate('AddTodoForm')} />
      ),
    };
  };

  render() {
    return (
      <View style={styles.appContainer}> {/* Added missing container style */}
        <View>
          <TextInput
            style={styles.form}
            value={this.state.titleText}
            onChangeText={this.handleFormTitleChange}
            placeholder={'Title'}
          />
        </View>
        <ScrollView>
          {/* Pass the item's id to the onChangeText handler */}
          {this.state.formItems.map(item => (
            <FormNewTodo
              key={item.id}
              onChangeText={(text) => this.handleformItemsChange(text, item.id)}
              value={item.text}
            />
          ))}
        </ScrollView>
        <Button onPress={this.handleSave} title='Save'/>
        <Button onPress={this.handleAddTodo} title='Add Todo'/>
      </View>
    )
  }
}

What Changed & Why

  1. Pass Item ID to Change Handler: In the render method, we now pass the item.id along with the input text to handleformItemsChange. This lets us exactly know which input is being edited, no more guesswork.
  2. Simplified State Update: The updated handler uses findIndex to locate the correct item in the array, then creates a new object with the updated text (to keep React state immutability rules). No more unreliable text filtering!
  3. Fixed State Typo: Your original code had a typo (formsItems instead of formItems) when updating state—this has been corrected to ensure state updates properly.
  4. Proper ID Reset: Removed the let keyword from id = 0 in handleSave to reset the global counter instead of creating a useless local variable.
  5. Added Missing Container Style: Added style={styles.appContainer} to the root View to apply your intended padding and background styles.

Quick Note on Your FormNewTodo Component

Make sure your FormNewTodo component correctly forwards the onChangeText and value props to its internal TextInput. For reference, here's a simple working version:

// Example FormNewTodo component
import React from 'react';
import { TextInput, StyleSheet } from 'react-native';

const FormNewTodo = ({ onChangeText, value }) => {
  return (
    <TextInput
      style={styles.input}
      onChangeText={onChangeText}
      value={value}
      placeholder="Enter todo item"
    />
  );
};

const styles = StyleSheet.create({
  input: {
    padding: 10,
    borderColor: '#ccc',
    borderWidth: 1,
    margin: 5,
    borderRadius: 4,
  },
});

export default FormNewTodo;

This should resolve your issue—now each dynamic TextInput will correctly update its own value in the state, and you can handle all user inputs reliably!

内容的提问来源于stack exchange,提问作者tkd1707

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:13:21