如何从特定单击的响应中删除数组中的索引

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从特定单击的响应中删除数组中的索引相关的知识,希望对你有一定的参考价值。

我正在构建一个测验/调查构建器,一种CMS界面,允许用户通过单击他们想要的问题类型来添加任意数量的问题。

首先,我的状态在App组件中设置如下:

state = {
  components: API.components,
  comps: []
}

管理屏幕具有选定数量的按钮,这些按钮将激活问题onClick。问题来自API.components。例如,我们有: - 欢迎辞 - 谢谢你的消息 - 是或否

/* 1. Generate a list of buttons with onClick props.addQuestion passing a fixed id via 'i' parameter */
const QuestionTypes = props => {  
  return (
    <div data-name='typequestion'>
      {props.details.map((el, i) => <div key={i}><button className="sm" onClick={() => props.addQuestion(i)}>{el.label}</button></div>)}
    </div>
  )
}

请参阅菜单问题截图:https://www.awesomescreenshot.com/image/3982311/8964261115690780c3f67d390ce08665

onClick,这些按钮中的每一个都将触发'addQuestion'方法,该方法将固定ID(键)传递给'selectComponent'函数,以将所选组件添加到comps []数组:

/* onClick, a method 'addQuestion' is called */
/* This method will setState and call a function selectComponent passing a key (id) in order to select the correct component */
addQuestion = key => {
  this.setState({
    comps: [...this.state.comps, this.selectComponent(key)]
  });
}

selectComponent函数有一个开关来传递正确的组件:

selectComponent = (key) => {
    switch(key) {
      case 0:
        return <WelcomeMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
        break;
      case 1:
        return <ThankYouMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
        break;
      case 2:
        return <YesNo details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
        break;
      default:
        return 'Please select a component from the left side menu'
    }
  }

这将为comps []数组添加一个元素:

[
  0: {element here ..}
  1: {element here ..} etc.
]

这是组件代码的示例:

const ThankYouMessage = props => (

  <section className="ui-component-view" data-name="thankyou">
    <img src={ThankYouImage} alt="x" />
    <h3>Thanks for completing our form!</h3>

    <div>
      <DeleteButton deleteQuestion={props.deleteQuestion} />
    </div>
  </section>

);

请参阅选定的欢迎消息组件截图:https://www.awesomescreenshot.com/image/3982315/f59e1bf79a31194aa3ee3ad2467658a0

问题:

如您所见,每个组件都有一个删除按钮。虽然每个组件都没有问题地添加到阵列中,但是当我单击删除按钮时,我找不到仅删除所选组件的方法。

我曾尝试使用.filter(),splice()但我没有为新创建或更新的数组列表提供正确的索引。我想用React的方式来做,而不是jQuery或javascript-ish。

删除按钮的示例。请注意,props.index传递的是原始单击的按钮id(key),它与新的comps []数组索引不匹配:

const DeleteButton = props => (

  <span className="deleteButton" onClick={() => props.deleteQuestion(props.index)}>&times;<small>Delete</small></span>

);

export default DeleteButton;

这里是删除方法:

deleteQuestion = e => {
    const comps = [...this.state.comps]

    // 2. here I need to add something that will DELETE ONLY the clicked button index for that component

    // 3. Update state
    this.setState({ comps });
}

请参阅App组件的完整代码:class App extends React.Component {

  state = {
    components: API.components,
    comps: [],
    multichoice: {}
  }

  selectComponent = (key) => {
    switch(key) {
      case 0:
        return <WelcomeMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
        break;
      case 1:
        return <ThankYouMessage details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
        break;
      case 2:
        return <YesNo details={this.state.components[key]} deleteQuestion={this.deleteQuestion} comps={this.state.comps} index={fuck} />
        break;
      default:
        return 'Please select a component from the left side menu'
    }
  }

  addQuestion = key => {

    this.setState({
      comps: [...this.state.comps, this.selectComponent(key)]
    });
  }

  deleteQuestion = e => {
    const comps = [...this.state.comps]

    // 2. here I need to add something that will DELETE ONLY the component related to the delete button

    // 3. Update state
    this.setState({ comps });
  }

  render() {
    return (
      <Container>
        <Row>
          <Col>
            <h1>Survey Builder </h1>
          </Col>
        </Row>
        <Row>
          <Col lg={3} className="border-right">
          <QuestionTypes addQuestion={this.addQuestion} details={this.state.components} />
          </Col>
          <Col lg={9}>
            <Row>
              <Col lg={12}>
                <QuestionEdit comps={this.state.comps} details={this.state.components} />
              </Col>
            </Row>
          </Col>
        </Row>
      </Container>
    )
  }
}

export default App;
答案

您不应该将组件保持在状态内(因为这会破坏组件的生命周期并且很难比较它们)。相反,只需保留键:

 addQuestion = key => {
  this.setState({
   comps: [...this.state.comps, key]
  });
 }

然后在render()中,将键映射到组件:

 {this.state.comps.map((key, index) => <SomeComponent    remove={() => this.removeQuestion(index)} />)}

现在removeQuestion可以简单地:

 removeQuestion(index) {
   this.setState(({ comps }) => ({ comps: comps.filter((_, i) => i !== index) }));
 }
另一答案

编辑:不应该在州上持有任何组件,只是代表问题的对象。

comps状态应该是不可变的,这意味着每次添加或删除问题时,您应该从旧的数组中创建一个新的数组,当前处于状态。

由于您没有使用任何高级状态管理器(如Redux等),此时也不应该使用,我建议在每个问题上都有一个数据属性,上面有问题ID。点击后,您可以从点击事件所携带的目标中获取问题ID,并使用它来确定问题项目在comps状态中的位置。有了它,创建一个新的comps状态,通过构造一个没有你刚刚删除的问题的新数组。

我还建议不要在这里使用开关/盒子,因为它无视open/close principle。我想你会找到一种字典方法,你可以将问题的类型映射到相应的组件,更加可扩展和可维护。

希望这可以帮助 :)

以上是关于如何从特定单击的响应中删除数组中的索引的主要内容,如果未能解决你的问题,请参考以下文章

如何通过单击按钮从反应状态挂钩数组中删除对象

从ViewPager android替换片段

如何删除numpy数组中的特定元素

如何使用python从数组中删除特定元素

如何将列表视图中的数据从一个片段发送到另一个片段

如何知道单击按钮的列表项的索引