【问题标题】:Update list of displayed components on deletion in React更新 React 中删除时显示的组件列表
【发布时间】:2019-08-07 10:33:09
【问题描述】:

在我使用 React 的道路上,我正在创建简单的待办事项应用程序,用户可以在其中添加/删除基本上是独立组件的任务。

我使用以下方法创建任务:

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'。如果我单击第一个上的删除按钮,则与该组件关联的对象将被删除,第二个成为第一个但它的状态。名称现在是“Foo”而不是“Bar”。

我认为我在反应中缺少正确的创建/删除/显示组件。

编辑:

用于移除被点击组件的方法:

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>
    );
}

}

在错误的视觉表示下,左侧的图像是删除前的图像,右侧是删除后的图像。虽然删除了带有“22”的卡片,但组件本身并没有被删除,只是传递了另一个对象。

【问题讨论】:

    标签: reactjs components react-props


    【解决方案1】:

    澄清一下,解决方案比预期的要简单。

    const showTasks = () =>  taskList.map((item, index) => (
            <SingleTask
                taskObj={item}
                removeTask ={removeTask}
                key = {item.id}
            />
            )
        )
    

    我将 map index 作为键传递,当我将其更改为 {item.id} 时,一切正常。

    【讨论】:

      【解决方案2】:

      简而言之,在声明tasksList.push(&lt;SingleTask taskObj={taskObj} removeTask ={this.removeTask}/&gt;);中,removeTask = {this.removeTask}应该变成removeTask = {() =&gt; this.removeTask(taskObj.id)}

      但是,我会重新考虑方法 addTaskshowTasks 的编写方式。虽然你写的方式没有错,但它在语义上是不正确的。这是我要做的:

      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>

      【讨论】:

      • 感谢您的回复,但很遗憾您更改后的结果是一样的。
      • 我不知道在哪里调用 removeCurrentTask,所以如果有帮助,我已经用代码 sn-p 更新了我的解决方案。
      • 这样叫:&lt;a title="Remove task" onClick={this.removeCurrentTask} className={ classNames( 'float-right btn-floating btn-smallx waves-effect waves-light listMenuBtn 反正结果是一样的。
      • 我明白了。那么你原来的removeTask = {this.removeTask} 应该变成removeTask = {(id) =&gt; this.removeTask(id)}。试试这个。
      • 我已按照您的建议进行了所有更改,但结果仍然相同,组件并没有真正删除,只是列表中的特定对象。由于所有更改,我在原始帖子中编辑了方法。
      猜你喜欢
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多