React Native中动态创建TextInput的实现问题求助
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
- Pass Item ID to Change Handler: In the
rendermethod, we now pass theitem.idalong with the input text tohandleformItemsChange. This lets us exactly know which input is being edited, no more guesswork. - Simplified State Update: The updated handler uses
findIndexto 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! - Fixed State Typo: Your original code had a typo (
formsItemsinstead offormItems) when updating state—this has been corrected to ensure state updates properly. - Proper ID Reset: Removed the
letkeyword fromid = 0inhandleSaveto reset the global counter instead of creating a useless local variable. - Added Missing Container Style: Added
style={styles.appContainer}to the rootViewto 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

