使用React以编程方式添加组件

时间:2019-04-26 09:48:33

标签: javascript reactjs components

我对React并不陌生,我正在尝试向已经存在的新组件中添加新组件,但是我不确定该怎么做。

因此,这里有Seances的列表以及添加更多内容的按钮:
SeanceManager.js

return (
  <MDBRow>
    <MDBCol md="6">
      <MDBCard>
        <MDBCardBody>
          <form>
            <p className="h4 text-center py-4">Sign up</p>
            <div className="grey-text">
              <MDBInput
                label="Type your email"
                icon="envelope"
                group
                type="email"
                validate
                error="wrong"
                success="right"
              />
              <MDBInput
                label="Type your password"
                icon="lock"
                group
                type="password"
                validate
              />
            </div>
            <div className="text-center py-4 mt-3">
              <MDBBtn color="cyan" type="submit" onClick={props.submitLogin}>
                Log in
              </MDBBtn>
            </div>
          </form>
        </MDBCardBody>
      </MDBCard>
    </MDBCol>
  </MDBRow>
);

通过按按钮添加更多内容,将弹出一个模式视图,最后它具有一个submit按钮,应添加Seance
AddSeanceModal.js

return (
  <Modal
    {...this.props}
    size="lg"
    aria-labelledby="contained-modal-title-vcenter"
    centered
  >
    <Modal.Header closeButton>
      <Modal.Title id="contained-modal-title-vcenter">Add Seance</Modal.Title>
    </Modal.Header>
    <Modal.Body>
      <div>
        <form>
          {/*First row*/}
          <MDBRow>
            <MDBCol md="4">
              <div className="custom-file">
                <input
                  type="file"
                  className="custom-file-input"
                  id="inputGroupFile01"
                  aria-describedby="inputGroupFileAddon01"
                />
                <label className="custom-file-label" htmlFor="inputGroupFile01">
                  Choose file
                </label>
              </div>
            </MDBCol>
          </MDBRow>

          {/*Second row*/}
          <MDBRow>
            <MDBCol md="4">
              <MDBInput
                onChange={this.changeHandler}
                type="text"
                id="materialFormRegisterPasswordEx4"
                name="algus_aeg"
                label="Algus Aeg"
                required
              />
            </MDBCol>
            <MDBCol md="4">
              <MDBInput
                onChange={this.changeHandler}
                type="text"
                id="materialFormRegisterPasswordEx4"
                name="lopp_aeg"
                label="Lõpp Aeg"
                required
              />
            </MDBCol>
          </MDBRow>

          {/*Third row*/}
          <MDBRow>
            <MDBCol md="4">
              <MDBInput
                onChange={this.changeHandler}
                type="text"
                id="materialFormRegisterPasswordEx4"
                name="aja_samm"
                label="Aja Samm"
                required
              />
            </MDBCol>
          </MDBRow>

          <Button variant="secondary" onClick={this.props.onHide}>
            Close
          </Button>
          <MDBBtn color="success" type="submit" className="float-right">
            Add Seance
          </MDBBtn>
        </form>
      </div>
    </Modal.Body>
  </Modal>
);

最后是Seance本身:
Seance.js

return (
  <div
    className="card"
    style={{ marginBottom: "7px" }}
    onClick={() => this.setState({ modalShow: true })}
  >
    <div className="card-body">
      <h5 className="card-title">Seance nr: {this.props.id}</h5>
      <p className="card-text">Start aeg: {this.props.startDate}</p>
      <p className="card-text">End aeg: {this.props.endDate}</p>
      <button type="button" className="close float-right" aria-label="Close">
        <span aria-hidden="true">×</span>
      </button>
      <ResultModal id={1} show={this.state.modalShow} onHide={modalClose} />
    </div>
  </div>
);

我还在沙盒上摆弄了一个小提琴: https://codesandbox.io/s/qloo1vqr7j?fontsize=14

目前,我有4个静态Seances,但它应以0开头,并在添加后添加更多。
会议上的X也应将其删除。

我尝试在SeanceManager.js中的状态上创建列表,但是我还没有理解如何从另一个组件AddSeanceModal向列表中添加组件。

1 个答案:

答案 0 :(得分:1)

有很多代码选择使应用程序无法动态运行。

首先,您需要利用container component处理与Seance状态有关的所有事物。其中包括addingremovingviewing。所有这些都需要由父级处理,该父级必须根据其state中的当前更新其子级。请按照本指南了解containers vs components

第二,您需要重构如何利用Seances。它们需要作为array存储在父母的state中。现在,它已经硬编码为4 <Seances />,无法删除/更新。

相反,您应该在array中创建objectstate中的seances: [ { id: "1", startDate: "2019-04-10 10:28:05.926-07", endDate: "2019-05-10 10:28:05.924-07" }, { id: "2", startDate: "2019-04-11 11:28:05.926-07", endDate: "2019-05-11 11:28:05.924-07" }, { id: "3", startDate: "2019-04-12 12:28:05.926-07", endDate: "2019-05-12 12:28:05.924-07" }, ...etc ];

array

您将利用Array.map来动态映射这些会议returnimplicitly <Seance id={id} />这些会议(为了易于阅读,我正在编写您的{{ 1}}内联组件):

<div>
  {seances.map(({ id, startDate, endDate }) => (
    <div key={id}>
     <h1>Seance nr: {id} </h1>
     <p>Start date: {startDate}</p>
     <p>End date: {endDate}</p>
     <button type="button" onClick={() => handleDeleteSeance(id)}>X</button>
    </div>
  ))}
</div>

现在,您将通过seance的seances属性利用Array.filterid数组中删除这些项目。用户单击“ X”按钮时,它将以特定的this.handleDeleteSeance调用id

handleDeleteSeance = id => {
  this.setState(prevState => ({
    ...prevState, // spread out any previous state not related to "seances"
    seances: prevState.seances.filter(seance => seance.id !== id) // this translates to: compare each "seance" within "seances" and implicitly return any that do NOT match the "id" that was clicked
  })
};

要将项目添加到seances数组中,您将利用spread operator,并添加具有从object收集的属性的form

handleSubmit = e => {
  e.preventDefault();
  const { id, startDate, endDate } = this.state;

  if (!id || !startDate || !endDate } return null; // if any properties are missing, don't add an item yet

  this.setState(prevState => ({
    ...prevState, // spread out any previous state not related to "seances"
    seances: [...prevState.seances, { id, startDate, endDate } ] // this translates to: spread out any previous seances and add a new object with "id", "startDate" and "endDate"
  });  
} 

使用数组示例(由于这是一个仅用于客户端的实现,因此我决定按数组位置进行过滤,因此不必处理生成唯一的id;但是,您可以根据需要使用uuid生成这些动态id):

Edit Class Component - Filter Data by Array Index


其他说明

  • 您的一个组件在let modalClose = () => this.setState({ modalShow: false });方法中包含一个render。 这是无效的,应将其定义为类方法。
  • 构建可重复使用的组件。您拥有一些组件,但随后又有一些组件驻留在另一个组件中(例如FileInput)。随着应用程序的增长,您可能需要在其他地方使用FileInput来获得另一种形式。
  • 在整个项目中整个使用ES6语法来简化代码。例如,您可以为props组件deconstruct Login像这样:const Login = ({ submitLogin }) => ( <MDBRow>...etc</MDBRow>);