在 React 中删除时更新显示的组件列表
Update list of displayed components on deletion in React
在我开始使用 React 的道路上,我正在创建简单的待办事项应用程序,用户可以在其中 add/remove 基本上是独立组件的任务。
我使用以下方法创建任务:
addTask(taskObj){
let tasksList = this.state.tasksList;
tasksList.push(taskObj);
this.setState({tasksList : tasksList});
}
我使用以下方法呈现组件(任务)列表:
showTasks(){
return (
this.state.tasksList.map((item, index) => {
return <SingleTask
taskObj={item}
removeTask = {(id) => this.removeTask(id)}
key = {index}/>;
})
);
}
删除特定任务的方法将任务的唯一 ID 作为参数,并根据此 ID 从任务列表中将其删除:
removeTask(uID){
this.setState(prevState => ({
tasksList: prevState.tasksList.filter(el => el.id != uID )
}));
}
但问题是,当我删除除最后一个项目之外的任何项目时,实际的组件列表似乎是相同的,只是将不同的对象传递给了这些组件。
例如:
假设我有 2 个创建的组件,如果我在第一个组件上设置 state.Name = 'Foo',在第二个组件上设置 state.Name='Bar'。如果我单击第一个上的删除按钮,与该组件关联的对象将被删除,第二个成为第一个,但它的 state.Name 现在是 'Foo' 而不是 'Bar'.
我想我在 React 中遗漏了正确的 creation/removing/displaying 组件。
编辑:
用于删除点击组件的方法:
removeCurrentTask(){
this.props.removeTask(this.props.taskObj.id);
}
SingleTask 组件:
class SingleTask extends Component{
constructor(props) {
super(props);
this.state={
showMenu : false,
afterInit : false,
id: Math.random()*100
}
this.toggleMenu = this.toggleMenu.bind(this);
}
toggleMenu(){
this.setState({showMenu : !this.state.showMenu, afterInit : true});
}
render(){
return(
<MDBRow>
<MDBCard className="singleTaskContainer">
<MDBCardTitle>
<div class="priorityBadge">
</div>
</MDBCardTitle>
<MDBCardBody className="singleTaskBody">
<div className="singleTaskMenuContainer">
<a href="#" onClick={this.toggleMenu}>
<i className="align-middle material-icons">menu</i>
</a>
<div className={classNames('singleTaskMenuButtonsContainer animated',
{'show fadeInRight' : this.state.showMenu},
{'hideElement' : !this.state.showMenu},
{'fadeOutLeft' : !this.state.showMenu && this.state.afterInit})}>
<a
title="Remove task"
onClick={this.props.removeTask.bind(null, this.props.taskObj.id)}
className={
classNames(
'float-right btn-floating btn-smallx waves-effect waves-light listMenuBtn lightRed'
)
}
>
<i className="align-middle material-icons">remove</i>
</a>
<a title="Edit title"
className={classNames('show float-right btn-floating btn-smallx waves-effect waves-light listMenuBtn lightBlue')}
>
<i className="align-middle material-icons">edit</i>
</a>
</div>
</div>
{this.props.taskObj.description}
<br/>
{this.state.id}
</MDBCardBody>
</MDBCard>
</MDBRow>
);
}
}
在错误的可视化表示下,左边的图像是删除前的,右边的是post-删除。虽然带有“22”的卡片被删除,但组件本身并没有被删除,只有另一个对象被传递给它。
简而言之,在语句tasksList.push(<SingleTask taskObj={taskObj} removeTask ={this.removeTask}/>);
中,removeTask = {this.removeTask}
应该变成removeTask = {() => this.removeTask(taskObj.id)}
.
但是,我会重新考虑方法 addTask
和 showTasks
的编写方式。虽然你写的方式没有错,但它在语义上是不合理的。这是我会做的:
addTask(taskObj){
let tasksList = this.state.tasksList;
tasksList.push(taskObj);
this.setState({tasksList : tasksList});
}
showTasks(){
return (
this.state.tasksList.map((item, index) => {
return <SingleTask
taskObj={item}
removeTask ={() => this.removeTask(item.id)}/>;
})
);
}
const SingleTask = (task) => {
const { taskObj } = task;
return <div onClick={task.removeTask}>
{ taskObj.title }
</div>
}
// Example class component
class App extends React.Component {
state = {
tasksList: [
{ id: 1, title: "One" },
{ id: 2, title: "Two" },
{ id: 3, title: "Three" },
{ id: 4, title: "Four" }
]
}
addTask = (taskObj) => {
let tasksList = this.state.tasksList;
tasksList.push(taskObj);
this.setState({tasksList : tasksList});
}
showTasks = () => {
return (
this.state.tasksList.map((item, index) => {
return <SingleTask
key={index}
taskObj={item}
removeTask ={() => this.removeTask(item.id)}/>;
})
);
}
removeTask(id) {
this.setState(prevState => ({
tasksList: prevState.tasksList.filter(el => el.id != id )
}));
}
render() {
return (
<div className="App">
<div> {this.showTasks()} </div>
</div>
);
}
}
// Render it
ReactDOM.render(
<App />,
document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
澄清一下,解决方案比预期的要简单。
在
const showTasks = () => taskList.map((item, index) => (
<SingleTask
taskObj={item}
removeTask ={removeTask}
key = {item.id}
/>
)
)
我将地图 index
作为键传递,当我将其更改为 {item.id}
时一切正常。
在我开始使用 React 的道路上,我正在创建简单的待办事项应用程序,用户可以在其中 add/remove 基本上是独立组件的任务。
我使用以下方法创建任务:
addTask(taskObj){
let tasksList = this.state.tasksList;
tasksList.push(taskObj);
this.setState({tasksList : tasksList});
}
我使用以下方法呈现组件(任务)列表:
showTasks(){
return (
this.state.tasksList.map((item, index) => {
return <SingleTask
taskObj={item}
removeTask = {(id) => this.removeTask(id)}
key = {index}/>;
})
);
}
删除特定任务的方法将任务的唯一 ID 作为参数,并根据此 ID 从任务列表中将其删除:
removeTask(uID){
this.setState(prevState => ({
tasksList: prevState.tasksList.filter(el => el.id != uID )
}));
}
但问题是,当我删除除最后一个项目之外的任何项目时,实际的组件列表似乎是相同的,只是将不同的对象传递给了这些组件。
例如: 假设我有 2 个创建的组件,如果我在第一个组件上设置 state.Name = 'Foo',在第二个组件上设置 state.Name='Bar'。如果我单击第一个上的删除按钮,与该组件关联的对象将被删除,第二个成为第一个,但它的 state.Name 现在是 'Foo' 而不是 'Bar'.
我想我在 React 中遗漏了正确的 creation/removing/displaying 组件。
编辑:
用于删除点击组件的方法:
removeCurrentTask(){
this.props.removeTask(this.props.taskObj.id);
}
SingleTask 组件:
class SingleTask extends Component{
constructor(props) {
super(props);
this.state={
showMenu : false,
afterInit : false,
id: Math.random()*100
}
this.toggleMenu = this.toggleMenu.bind(this);
}
toggleMenu(){
this.setState({showMenu : !this.state.showMenu, afterInit : true});
}
render(){
return(
<MDBRow>
<MDBCard className="singleTaskContainer">
<MDBCardTitle>
<div class="priorityBadge">
</div>
</MDBCardTitle>
<MDBCardBody className="singleTaskBody">
<div className="singleTaskMenuContainer">
<a href="#" onClick={this.toggleMenu}>
<i className="align-middle material-icons">menu</i>
</a>
<div className={classNames('singleTaskMenuButtonsContainer animated',
{'show fadeInRight' : this.state.showMenu},
{'hideElement' : !this.state.showMenu},
{'fadeOutLeft' : !this.state.showMenu && this.state.afterInit})}>
<a
title="Remove task"
onClick={this.props.removeTask.bind(null, this.props.taskObj.id)}
className={
classNames(
'float-right btn-floating btn-smallx waves-effect waves-light listMenuBtn lightRed'
)
}
>
<i className="align-middle material-icons">remove</i>
</a>
<a title="Edit title"
className={classNames('show float-right btn-floating btn-smallx waves-effect waves-light listMenuBtn lightBlue')}
>
<i className="align-middle material-icons">edit</i>
</a>
</div>
</div>
{this.props.taskObj.description}
<br/>
{this.state.id}
</MDBCardBody>
</MDBCard>
</MDBRow>
);
}
}
在错误的可视化表示下,左边的图像是删除前的,右边的是post-删除。虽然带有“22”的卡片被删除,但组件本身并没有被删除,只有另一个对象被传递给它。
简而言之,在语句tasksList.push(<SingleTask taskObj={taskObj} removeTask ={this.removeTask}/>);
中,removeTask = {this.removeTask}
应该变成removeTask = {() => this.removeTask(taskObj.id)}
.
但是,我会重新考虑方法 addTask
和 showTasks
的编写方式。虽然你写的方式没有错,但它在语义上是不合理的。这是我会做的:
addTask(taskObj){
let tasksList = this.state.tasksList;
tasksList.push(taskObj);
this.setState({tasksList : tasksList});
}
showTasks(){
return (
this.state.tasksList.map((item, index) => {
return <SingleTask
taskObj={item}
removeTask ={() => this.removeTask(item.id)}/>;
})
);
}
const SingleTask = (task) => {
const { taskObj } = task;
return <div onClick={task.removeTask}>
{ taskObj.title }
</div>
}
// Example class component
class App extends React.Component {
state = {
tasksList: [
{ id: 1, title: "One" },
{ id: 2, title: "Two" },
{ id: 3, title: "Three" },
{ id: 4, title: "Four" }
]
}
addTask = (taskObj) => {
let tasksList = this.state.tasksList;
tasksList.push(taskObj);
this.setState({tasksList : tasksList});
}
showTasks = () => {
return (
this.state.tasksList.map((item, index) => {
return <SingleTask
key={index}
taskObj={item}
removeTask ={() => this.removeTask(item.id)}/>;
})
);
}
removeTask(id) {
this.setState(prevState => ({
tasksList: prevState.tasksList.filter(el => el.id != id )
}));
}
render() {
return (
<div className="App">
<div> {this.showTasks()} </div>
</div>
);
}
}
// Render it
ReactDOM.render(
<App />,
document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
澄清一下,解决方案比预期的要简单。
在
const showTasks = () => taskList.map((item, index) => (
<SingleTask
taskObj={item}
removeTask ={removeTask}
key = {item.id}
/>
)
)
我将地图 index
作为键传递,当我将其更改为 {item.id}
时一切正常。