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

时间:2019-04-20 12:44:59

标签: javascript arrays reactjs

我正在构建一个测验/调查生成器,一种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式。

“删除”按钮示例。请注意,props.index正在传递原始单击的按钮ID(键),该ID与新comps []数组索引不匹配:

const DeleteButton = props => (

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

);

export default DeleteButton;

这里的Delete方法:

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组件的完整代码:     App类扩展了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;

2 个答案:

答案 0 :(得分:1)

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

if(size >= PTRDIFF_MAX)

然后在 addQuestion = key => { this.setState({ comps: [...this.state.comps, key] }); } 内,将密钥映射到组件:

render()

现在 {this.state.comps.map((key, index) => <SomeComponent remove={() => this.removeQuestion(index)} />)} 可以简单地是:

removeQuestion

答案 1 :(得分:0)

编辑: 不应将任何组件保留在状态上,仅应使用表示问题的对象。

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

由于您没有使用任何高级状态管理器(例如Redux等),并且此时您也不应该使用,因此建议您在每个问题上都分配一个数据,并在上面加上问题ID。单击后,您可以从点击事件中携带的目标中获取问题ID,并使用它来找出问题项目在comps状态下的位置。有了它后,通过构造一个新数组comps来创建新的<template> {{ countDown }} </template> <script> export default { data() { return { countDown : 10 } }, method: { countDownTimer() { if(this.countDown > 0) { setTimeout(() => { this.countDown -= 1 this.countDownTimer() }, 1000) } } } created: { this.countDownTimer() } } </script> 状态,该数组不存在您刚刚删除的问题。

我也建议不要在此使用开关/盒,因为它违反了open/close principle。我想您会找到一种字典方法,在其中将问题的类型映射到相应的组件上,从而更加可扩展和可维护。

希望这会有所帮助:)