React中从state取数据并编辑表单元素的问题求助
Let's break down and fix the issues you're facing step by step:
1. First Critical Bug: Missing Return in map (App Component)
In your App component's render method, the map function doesn’t return the <Todo> component. That means none of your Todo items are actually rendered to the DOM—so clicking the button does nothing at all. Fix this by adding a return (or using implicit return with parentheses):
// In App's render method {this.state.todos.map((todo, index) => { return <Todo key={index} index={index} toggle={this.toggle} todo={todo} currentEditIndex={this.state.index} updateTodo={this.updateTodo} /> })}
2. Fix the Editing State Logic
Right now, your global editing state makes all Todo components switch to edit mode when toggled. Instead, we’ll use the stored index in state to target only the clicked Todo for editing:
- Remove the
editingproperty from App’s state (we don’t need it anymore—index !== nullwill tell us if we’re in edit mode) - In the Todo component, check if its
indexmatches thecurrentEditIndexfrom props, instead of relying on a global flag.
3. Replace the Broken update Function with updateTodo
Your original update function references this.state.todo, but your App’s state doesn’t have a todo property. Instead, add a method that updates the specific todo in the todos array using the stored index:
// Add this to your App component updateTodo = (updatedTodo) => { const newTodos = [...this.state.todos]; newTodos[this.state.index] = updatedTodo; this.setState({ todos: newTodos, index: null }); // Reset index to exit edit mode after save }
4. Simplify the toggle Function
Update the toggle to either set the index to the clicked item, or reset it if we’re already editing that item:
// In App component toggle = (index) => { this.setState(prevState => ({ index: prevState.index === index ? null : index })); }
5. Update the Todo Component
Modify it to only show the edit form for the currently selected Todo:
class Todo extends Component { render() { const { index, currentEditIndex, todo, toggle, updateTodo } = this.props; // Only render EditForm if this todo is the one being edited if (currentEditIndex === index) { return <EditForm todo={todo} updateTodo={updateTodo} /> } return ( <li> <div>{todo.date}</div> <div>{todo.description}</div> <button onClick={() => toggle(index)}>Edit</button> </li> ) } } export default Todo;
6. Fix the EditForm Component
Ensure it correctly initializes state from props and submits changes back to the App:
class EditForm extends Component { constructor(props){ super(props); // Handle both Date objects and string dates from props const startDate = typeof props.todo.date === 'string' ? new Date(props.todo.date) : props.todo.date; this.state = { startDate, description: props.todo.description } } handleSubmit = (e) => { e.preventDefault(); const updatedTodo = { date: this.state.startDate, description: this.state.description }; // Call the parent's update method to save changes this.props.updateTodo(updatedTodo); } handleChange = (date) => { this.setState({ startDate: date }); } updateDesc = (e) => { this.setState({ description: e.target.value }); } render() { return ( <form onSubmit={this.handleSubmit}> <DatePicker selected={this.state.startDate} onChange={this.handleChange} showTimeSelect timeFormat="HH:mm" dateFormat="yy-MM-dd, hh:mm" timeCaption="time" /> <textarea value={this.state.description} onChange={this.updateDesc} /> <button type="submit">Save</button> </form> ) } } export default EditForm;
7. Final Corrected App Component
Here’s the full fixed App component with all changes integrated:
class App extends Component { constructor() { super(); this.state = { todos: [], index: null }; // Removed unused "editing" state } toggle = (index) => { this.setState(prevState => ({ index: prevState.index === index ? null : index })); } createTodo = (todo) => { const newArr = [...this.state.todos, todo]; // Simplified array push this.setState({ todos: newArr }); } updateTodo = (updatedTodo) => { const newTodos = [...this.state.todos]; newTodos[this.state.index] = updatedTodo; this.setState({ todos: newArr, index: null }); } render () { return ( <ul> {this.state.todos.map((todo, index) => { return ( <Todo key={index} index={index} toggle={this.toggle} todo={todo} currentEditIndex={this.state.index} updateTodo={this.updateTodo} /> ) })} </ul> ); } } export default App;
Key Fixes Recap:
- Fixed the missing return in
mapso Todo components actually render - Replaced global edit mode with index-based targeting to only edit the clicked Todo
- Added a proper
updateTodomethod to modify the specific todo in the array - Corrected date parsing in EditForm to handle both string and Date inputs
- Ensured the edit form submits changes back to the App and exits edit mode automatically
内容的提问来源于stack exchange,提问作者Umbro

