反应模态总是采用映射函数的最后一个元素



我目前正在创建一个 React todo 应用程序。所以基本上我有两个组件TodoList和TodoItem

TodoList 组件将接收一个由标题作为属性组成的对象数组,并使用 TodoItem 组件通过此映射

在我的 TodoItem 组件中,用户可以选择编辑或删除项目。如果用户选择编辑,则模式将使用文本区域与现有标题一起显示。但是,我在实现此功能时遇到问题,因为模态将始终与数组的最后一个元素一起显示。

待办事项列表组件

import React, { Component } from 'react'
import TodoItem from './TodoItem'
import { connect } from 'react-redux'
import { clear_todo } from '../store/actions/todoActions'
class Todolist extends Component {
clearList = (e) => {
e.preventDefault()
this.props.clearList(clear_todo());
}
handleChange = (index, title) => {
this.setState({
[index]: title
})
}
render() {
const { items, editItem } = this.props.todo
return (
<ul className="list-group my-5">
<h3 className="text-capitalize text-center">
Todo List
</h3>
{
items.map((item, index) => {
const editedTitle = item.title
return (<TodoItem key={item.id} title={item.title}
id={item.id}
editedTitle={editedTitle}
onChange={this.handleChange}
editItem={editItem} />)
})
}
<button className="btn btn-danger btn-block text-capitalize mt-5" onClick={this.clearList}> Clear List </button>
</ul>
)
}
}
const mapStateToProps = state => {
return {
todo: state.todo
}
}
const mapDispatchToProps = dispatch => {
return {
clearList: (clear_todo) => { dispatch(clear_todo) }
}
}

export default connect(mapStateToProps, mapDispatchToProps)(Todolist)

待办事项组件

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { delete_todo, edit_todo, toggle_edit } from '../store/actions/todoActions'
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Input } from 'reactstrap';
import TodoEditItem from './TodoEditItem'
class Todoitem extends Component {
// constructor(props) {
//   super(props)
//   this.state = {
//     [props.id]: props.title
//   }
// }

handleEdit = (id, title) => {
this.props.editTodo(edit_todo(id, title))
}
toggleEdit = (editItem, title) => {
this.props.toggleEdit(toggle_edit(!editItem))
// this.initializeTitle(title)
}
handleDelete = (id) => {
this.props.deleteTodo(delete_todo(id))
}
// onChange = (e, id) => {
//   this.setState({
//     [id]: e.target.value
//   })
// }
componentDidMount() {
// console.log(this.props)
// this.initializeTitle(this.props.title)
this.setState({
[this.props.id]: this.props.editedTitle
})
console.log(this.state)
}

render() {
// console.log(this.state)
let { id, title, editItem, editedTitle, index } = this.props
console.log(id)
// console.log(index)
// let { item } = this.state
return (
<div>
<li className="list-group-item text-capitlize d-flex justify-content-between my-2">
<h6>{title}</h6>
<div className="todo-icon">
<span className="mx-2 text-success" onClick={this.toggleEdit.bind(this, editItem)} >
<i className="fas fa-pen"></i>
</span>
<span className="mx-2 text-danger" onClick={this.handleDelete.bind(this, id)}>
<i className="fas fa-trash"></i>
</span>
</div>
<Modal isOpen={editItem}>
<ModalHeader>Edit Todo Item</ModalHeader>
<ModalBody>
<Form>
<FormGroup row>
<Input type="textarea" name="text" value={this.state ? this.state[id] : ""} onChange={this.props.onChange} />
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.handleEdit.bind(this, id, editedTitle)}>Save</Button>{' '}
<Button color="secondary" onClick={this.toggleEdit.bind(this, editItem)}> Cancel</Button>
</ModalFooter>
</Modal>
</li>
{/* {editItem ? <TodoEditItem title={title} editItem={editItem} /> : ''} */}
</div>
)
}
}

const mapDispatchToProps = dispatch => {
return {
deleteTodo: (delete_todo) => { dispatch(delete_todo) },
editTodo: (edit_todo) => { dispatch(edit_todo) },
toggleEdit: (toggle_edit) => { dispatch(toggle_edit) },
}
}

export default connect(null, mapDispatchToProps)(Todoitem)

示例图像

待办事项的图像

模态的图像

正如您从TodoItem的图像中看到的那样,我正在尝试编辑"倒垃圾",但我的文本区域已预填充为最后一个元素。

你使用相同的变量来确定TodoItem的所有打开状态。结果是它似乎只从数组中获取最后一个值,但实际上每个模态都同时打开,最后一个是唯一可见的模态。

// editItem here is used to determine the open state of both modals
const { items, editItem } = this.props.todo 
...
{
items.map((item, index) => {
const editedTitle = item.title
return (
<TodoItem 
key={item.id} 
title={item.title}
id={item.id}
editedTitle={editedTitle}
onChange={this.handleChange}
editItem={editItem}            // Same value
/>
)
})
}
...
let { editItem } = this.props
<Modal isOpen={editItem}>             // All will open and close at the same time

相反,请使用不同的标志,或者只是像这样管理每个子项中的打开状态:

<span className="mx-2 text-success" onClick={() => this.setState({open: true})} >
<i className="fas fa-pen"></i>
</span>
...
<Modal isOpen={this.state.open}>

最新更新