Próbuję usunąć wiele div, które zostały wygenerowane za pomocą przycisku dodawania. Mam problem ze zrozumieniem, w jaki sposób mogę wysłać identyfikator nadrzędnego elementu div do metody usuwania przekazanej z podrzędnego elementu div. Ponadto, jeśli mogę zapisać identyfikator div w stanie, aby wykonać proces usuwania. Mój kod jest następujący. Doceniam twoje uwagi i sugestie.

constructor(props) {
    super(props);
    this.state = {
      names: [],
      inputValue: '',
      id: [],
      count: 1,
      hostname: '',
      devname: '',
      sID: '',
    }
    this.addRow = this.addRow.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
    this.deleteRow = this.deleteRow.bind(this)
  }

addRow() {
    this.setState({ count: this.state.count + 1 })
    console.log(`Increase count: ${this.state.count}`)
  };

  renderDivs() {
    let count = this.state.count, uiItems = [];
    var { names } = this.state;
    let options2 = names.map(name2 => {
      return { value: name2.name, label: name2.name };
    })
    while (count--)
      uiItems.push(
        <div className="newHost" id="dynamic">
          <div className="hostInput">
            <input type="text" placeholder="Enter Name"
              onChange={this.handleChangeHN.bind(this)}
            />
          </div>
          <div className="hostInput">
            <Select
              placeholder="Pick Dev Name..."
              styles={colourStyles}
              options={options2}
              onChange={this.handleChangeDN}
            />
          </div>
          <div className="hostInput">
            <button className="btn btn-danger" type="button" onClick={this.deleteRow}>Remove</button>
          </div>
        </div>
      )
    return uiItems;
  }

  deleteRow(currentID) {
    // const changedID = this.state.id.filter(i => i.id !== currentID)
    // this.setState({changedID});
    // console.log(`Clicked: ${currentID}`);
    // this.setState({ count: this.state.count - 1 })
    console.log("delete");
  };

render() {
    let options = sData.map(name => {
      return { value: name.name, label: name.name };
    })

    return (
      <div className="wrapper">
        <div className="form-wrapper">
          <Toolbar />
          <form className="form" onSubmit={this.handleSubmit}>
            <label className="label1">Select SaleID</label> <hr />
            <div>
              <Select
                value={this.state.inputValue}
                onChange={this.handleChange}
                options={options}
              />
              <div style={{ color: 'red', marginTop: '5px' }}>
                {this.state.validationError}
              </div>
              <br />
            </div>
            <label className="label1">Create New Sale</label>
            <hr />
            <div className="addButton">
              <button type="button" onClick={this.addRow}>Add</button>
              {this.renderDivs()}
            </div>
            <hr />
            <div className="submitButton">
              <button type="submit">Submit</button>
            </div>
          </form>
        </div>
      </div>
    )
  }

Z góry dziękuję!

0
Shivani Bali 19 listopad 2019, 22:26
Twoja funkcja deleteRow powinna być deleteRow(event) i wewnątrz tej funkcji możesz uzyskać dostęp do identyfikatora rodzica: event.target.parentNode.id.
 – 
Alan Omar
19 listopad 2019, 22:59
Nie wiesz, co masz na myśli, usuwając wiele elementów div. Ale w następującym Codesandbox utworzyłem przykład listy dynamicznej. Przechowuj dynamiczną tablicę w stanie i zaktualizuj stan za pomocą dodawania/usuwania. Ważne jest, aby uzyskać odpowiednią strukturę danych, aby łatwiej było obsługiwać aktualizacje.
 – 
AWolf
19 listopad 2019, 23:29
Gdzie definiujesz sData?
 – 
Matt Croak
19 listopad 2019, 23:57
- sData nie ma nic wspólnego z przyciskiem usuwania, ale jeszcze do wyjaśnienia, służy do pobierania danych z pliku pamięci podręcznej i wyświetlania w rozwijanym menu.
 – 
Shivani Bali
20 listopad 2019, 00:01
@alan_jouhar: Nie jestem pewien, co masz na myśli, mówiąc o parentNode.id. Tutaj chcę przekazać nadrzędny identyfikator div („dynamiczny) w metodzie deleteRow (), a następnie pobrać ten identyfikator przekazany parametr i odpowiednio zaktualizować stan. Nie jestem jednak pewien, jak to zrobić.
 – 
Shivani Bali
20 listopad 2019, 00:01

1 odpowiedź

Programując w React należy najpierw zapomnieć o identyfikatorach html. Kiedy dodajesz lub usuwasz wiersz, masz do czynienia z danymi, a nie elementami html. Twój przykład nie zawiera wszystkich komponentów kodu i brakuje w nim funkcji handleChangeHN i handleChangeHN, więc podam tylko przykład odpowiednich części kodu:

constructor(props) {
    super(props);
    this.state = {
      rows: [],
    }
    //...
}

addRow() {
    const newRow = {
        name: '',
        devName: '',
    };
    this.setState({ rows: [...this.state.rows, newRow] })
};

deleteRow(position) {
    this.setState({ rows: this.state.rows.filter((_, i) => i !== position) })
}

renderDivs() {
    const { rows } = this.state;
    const options2 = rows.map(name2 => {
      return { value: name2.name, label: name2.name };
    });
    return rows.map( (row, i) => (
        <div className="newHost" key="_{i}">
          <div className="hostInput">
            <input type="text" placeholder="Enter Name"
              value={row.name}
              onChange={this.handleChangeHN.bind(this)}
            />
          </div>
          <div className="hostInput">
            <Select
              placeholder="Pick Dev Name..."
              styles={colourStyles}
              options={options2}
              value={row.devName}
              onChange={this.handleChangeDN}
            />
          </div>
          <div className="hostInput">
            <button className="btn btn-danger" type="button" onClick={() => this.deleteRow(i)}>Remove</button>
          </div>
        </div>
    ));
}

PS: używanie iteratora jako klucza key="_{i}" nie jest dobrą praktyką, ale ponieważ masz tylko pola wejściowe użytkownika, nie można ich używać jako identyfikatora. Inną opcją byłoby użycie generatora losowych identyfikatorów lub po prostu przechowywanie liczby kliknięć w stanie i używanie go jako identyfikatora podczas dodawania nowych wierszy.

PPS: na marginesie, nie należy wiązać komponentów obsługujących funkcje podczas renderowania tak, jak to robisz onChange={this.handleChangeHN.bind(this)}. Spowoduje to utworzenie nowej funkcji za każdym razem, gdy komponent jest renderowany, więc jest to powolny wyciek pamięci. Powiąż funkcje tak jak w konstruktorze lub po prostu użyj składni ecmascript 6 handleChangeHN = () => {....

0
Dimitri L. 20 listopad 2019, 01:10
Dziękuję za dokładny wkład. Tutaj zamiast wierszy muszę użyć (nazwy), ponieważ w nim dodaję dane wyciągnięte z zaplecza i muszę to pokazać w jednym z rozwijanych pod głównym div. Powyższe rozwiązanie nie ma pełnego zastosowania, ponieważ muszę usunąć nadrzędny element DIV, ale pętla nie jest wykonana prawidłowo. Naprawdę musiałbym to omówić więcej, daj mi znać, jeśli potrzebujesz całego pliku źródłowego?
 – 
Shivani Bali
20 listopad 2019, 19:11