【问题标题】:Remove Item on click in React [duplicate]在 React 中单击时删除项目 [重复]
【发布时间】:2019-12-19 21:52:47
【问题描述】:

我有一个包含 3 个名称的名称列表。单击任何 1 时,您可以编辑和保存。该值更新到列表中。现在我可以添加我想要的任何名称,但我无法删除/删除任何名称。

This is how it looks in the beginning

On clicking a name (the whole container) it looks like this

我可以将新名称添加回 div like this

我可以添加任意数量的内容,例如 like this

现在我希望能够单击十字图标并删除我想要的整个元素。它应该从页面中消失。其他元素应该从上到下取而代之。删除/删除功能应该在输入和带有名称的 div 中。

名称组件(名称从这里提取到下面的那个)

import Sukhdev from '../../../src/components/sukhdev';
import React from 'react';

export default { title: 'Sukhdev' };

const names = [{
    firstName: "Mahatma",
    lastName: "Gandhi"
}, {
    firstName: "Shivaji",
    lastName: "Maharaj"
}, {
    firstName: "Bhagat",
    lastName: "Singh"
},
]

export const sukhdev = () => {
    return(
    <Sukhdev names={names}/>
    ) 
}

父组件

import React, { Component } from 'react';
import FirstName from './firstName';
import LastName from './lastName';
import TextArea from './textArea'
import styles from './styles';


export default class Sukhdev extends Component {
  constructor(props) {
    super(props);
      const {names} = this.props;
      const updatedNames = names.map((name) => ({...name, ...{isEditable: false}})); 
      this.state = {
        userNames: updatedNames
      }
  }

 inputNamesHandler = (namesIndex) => {
    const updatedUserNameDetails = [...this.state.userNames];
    updatedUserNameDetails[namesIndex].isEditable = true;
    this.setState({userNames: updatedUserNameDetails})
  }

  saveButton = (inputValue, index) => {
    const {userNames} = this.state; 
    const newNames = [...userNames];
    newNames[index] = {...newNames[index], isEditable: false, firstName: inputValue, lastName: ''};
    this.setState({
      userNames: newNames
    })
  }

  addChild = () => {
    const createInputs = [...this.state.userNames];
    createInputs.push({firstName: '', lastName: '', isEditable: true});
    this.setState({
      userNames: createInputs
    })
  }

   ------> // This is where the changes need to be made
  deleteRow = (index) => {
    const postDelete = [...this.state.userNames];
    postDelete.slice(index, 1);
    this.setState({
      userNames: postDelete
    })
  }

  render() {
      return <div>
          <h1>Names</h1>
          <button onClick={this.addChild} style={styles.button}>Add New</button>
          <div>
              {this.state.userNames.map((nameDetails, index) => {
                  if(nameDetails.isEditable) {
                    return <div>
                      <TextArea clicked={(name) => this.saveButton(name, index)}/>
                      </div>;
                  } else {
                    return <div style={styles.namesContainer}>
                    <div onClick={() => this.inputNamesHandler(index)} style={styles.innerContainerComponent}>
                    <div style={styles.firstMargin}><FirstName firstName={nameDetails.firstName}></FirstName></div>
                    <div><LastName lastName={nameDetails.lastName}></LastName></div>
                    </div>
                    <img src={require('../../images/cancel.png')} style={styles.crossBtn} onClick={() => this.deleteRow(index)} />
                    </div>
                  }
              })}   
          </div> 
          </div>     
    }
}

文本区域/输入组件

import React, { Component } from "react";
import styles from './styles'

export default class TextArea extends Component {
    constructor(props) {
        super(props);
        this.state = {value:''}

        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(event) {
        this.setState({value: event.target.value});
    }

    render() {
        return (
            <div>
                <div style={styles.inputContainer}>
                <input type="text" style={styles.textField} value={this.state.value} onChange={this.handleChange}></input>
                <button type="submit" style={styles.saveButton} onClick={() => this.props.clicked(this.state.value)}>Save</button>
                <img src={require('../../images/cancel.png')} style={styles.crossBtn} />
                </div>
            </div>
        )

    }
}

父组件通过这种方式导入名字和姓氏

import React, {Component} from 'react';

export default class FirstName extends Component {
    render() {
        return <div>{this.props.firstName}</div>
    }
}

姓氏也与上面给出的代码类似。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    slice 不会修改原始数组,而是返回具有修改值的新数组。您需要将其分配给新变量或使用其他方法删除该值。

    let newArray = postDelete.slice(index, index + 1);
    this.setState({
      userNames: newArray
    })
    

    事实上,由于slice 不会改变数组,你可以简化为:

    this.setState((prevState) => ({
      userNames: prevState.userNames.slice(index, index + 1)
    )})
    

    但是,要完成此特定任务,您应该使用不同的方法,例如 filter

    this.setState((prevState) => ({
      userNames: prevState.userNames.filter((v,i) => i != index)
    )})
    

    这将遍历数组并过滤掉所有不满足条件的。第一个参数是当前值,第二个是索引。所以我们只想保留与我们的索引变量不匹配的值。

    【讨论】:

    • 这个问题是,如果我点击第二个和第三个元素,它会删除所有项目。如果我点击第一个,其他两个将被删除。
    • 啊,我没有对这里的实际用例给予足够的关注。我会编辑我的答案。 slice 需要一个开始和结束索引,所以我们想从给定索引开始并切到下一个位置(+1)
    • 现在只剩下我要删除的 div 了。我知道 slice 返回我们删除的一个元素,但我希望能够删除该 div 并显示其他元素。现在发生的事情恰恰相反。
    • 有道理。那么切片是错误的方法。而是使用过滤器。 .filter((value, i) =&gt; i != index)
    • 你能告诉我哪里出错了吗? imgur.com/a/qgYMtlR
    【解决方案2】:

    class App extends React.Component {
      state = {
        users: [
          {
            firstName: "Lionel",
            lastName: "Messi"
          },
          {
            firstName: "Cristiano",
            lastName: "Ronaldo"
          },
          {
            firstName: "Neymar",
            lastName: "Jr."
          },
          {
            firstName: "Zlatan",
            lastName: "Ibrahimovic"
          },
          {
            firstName: "Ricardo",
            lastName: "Kaka"
          }
        ]
      };
    
      updateUsers = (updatedUser, index) => {
        var users = [...this.state.users];
        users[index] = updatedUser;
        this.setState({
          users
        });
      };
    
      deleteUser = index => {
        var users = [...this.state.users];
        users.splice(index, 1);
        this.setState({
          users
        });
      };
    
      render() {
        return (
          <div>
            {this.state.users.map((user, index) => {
              return (
                <PlayerBox
                  user={user}
                  key={Math.random()}
                  index={index}
                  updateUsers={this.updateUsers}
                  deleteUser={this.deleteUser}
                />
              );
            })}
            <h1> {JSON.stringify(this.state.users)} </h1>
          </div>
        );
      }
    }
    
    class PlayerBox extends React.Component {
      state = {
        editMode: false,
        firstName: "",
        lastName: ""
      };
    
      componentDidMount() {
        const { firstName, lastName } = this.props.user;
        this.setState({
          firstName,
          lastName
        });
      }
    
      updateParent = () => {
        const { index, updateUsers } = this.props;
        updateUsers(
          {
            firstName: this.state.firstName,
            lastName: this.state.lastName
          },
          index
        );
        this.setState({
          editMode: false
        });
      };
    
      deleteUser = () => {
        const { deleteUser, index } = this.props;
        this.setState({
          editMode: false
        });
        deleteUser(index);
      };
    
      render() {
        const { firstName, lastName } = this.props.user;
        return this.state.editMode ? (
          <div>
            <div>
              <input
                type="text"
                value={this.state.firstName}
                onChange={e =>
                  this.setState({
                    firstName: e.target.value
                  })
                }
              />
              <input
                type="text"
                value={this.state.lastName}
                onChange={e =>
                  this.setState({
                    lastName: e.target.value
                  })
                }
              />
              <button type="submit" onClick={this.updateParent}>
                Save
              </button>
              <button onClick={this.deleteUser}> Delete </button>
            </div>
          </div>
        ) : (
          <div
            onClick={() =>
              this.setState({
                editMode: true
              })
            }
          >
            {firstName} {lastName}
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <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>
    <div id="root"></div>

    【讨论】:

    • 您的建议会改变状态,不应使用。你可以改成let users = [...this.state.users];
    • var users = this.state.users; users[index] = updatedUser; 你不能那样做。您正在直接设置状态。 users 是对state.users 的引用,它不是一个新数组。
    • 那不是真的,它仍然引用同一个数组。看看这个answer。在 javascript 中将数组和对象分配给变量时,您是在为其分配一个引用,而不是对象/数组本身。
    • 你是绝对正确的 Brian 和 JMadelaine。谢谢你为我指出这一点。让我纠正答案。我确实学到了一些东西。再次感谢。
    • 非常感谢您的解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 2016-09-21
    • 2021-01-18
    相关资源
    最近更新 更多