1

I wanted to remove a row from the table with the function 'deleteRow(btn)' when pressing the button, but I get this error 'Cannot read properties of undefined (reading 'parentNode')'. What could I add or correct to successively drop a row from a table?

App.js

class App extends React.Component{

  constructor(props) {
    super(props);  

    this.state = {
      
      fotos: [],
      restaurantes:[],
     
    }

  }

   deleteRow=(btn)=> {
         var row = btn.parentNode.parentNode;
         row.parentNode.removeChild(row);
   }

   render(){  

      const { fotos, restaurantes } = this.state;

      <div className="container">
         <Tabela dadosFotos={fotos} restaurante={this.deleteRow} />
      </div>
   }
     

Tabela.js

import React from "react";

const CorpoTabela = (props) => {

const rows = props.dadosDasFotos.map((row) => {
    return(
    <tr key={row.idFoto}>
        <td>{row.nomeRestaurante}</td>
        <td>
             <button className="btn btn-outline-danger" 
                 onClick={()=>props.restauranteAremover(row.idFoto)}>
                 Delete restaurante
             </button>
        </td>
     </tr>        
    )  
})

return(<tbody>{rows}</tbody>)
}

class Tabela extends React.Component{

    render(){
        
        const { dadosFotos, restaurante }=this.props
        
        return(
            <table className="table table-striped">
                <CorpoTabela dadosDasFotos={dadosFotos} restauranteAremover={restaurante}/>
            </table>          
        )
    }
}
2
  • 1
    Why are you trying to directly manipulate the DOM, an anti-pattern in React, instead of deleting the element from the fotos array in state? You need to update the state so React triggers a rerender. Just deleting DOMNodes won't trigger your UI to rerender an updated view. Commented Sep 11, 2021 at 21:22
  • Your delete function is taking id not any HTML. In react like above comment you need to delete it from the list using filter react will react to your change and rerender Commented Sep 11, 2021 at 21:25

2 Answers 2

3

You should not be manipulating the DOM as this is an anti-pattern in React, instead you should update the state you are rendering from.

Delete by idFoto.

deleteRow = (idFoto)=> {
  this.setState(prevState => ({
    fotos: prevState.fotos.filter(el => el.idFoto !== idFoto
  }))
}

In the child pass the id to the delete handler.

<button className="btn btn-outline-danger" 
  onClick={() => props.restauranteAremover(row.idFoto)}>
  Delete restaurante
</button>
Sign up to request clarification or add additional context in comments.

4 Comments

There’s another property in state.
@SanishJoseph That's ok, class component's setState shallow merges state updates, so you don't need to handle this manually.
First of all thanks is exactly what I asked but how could I also delete the data from the database, this table is fetching data from a database. When I refresh the page, the data reappears. @DrewReese
@GuyPeace That depends entirely on the database and the backend service(s) handling your APIs. I guess you'd implement a DELETE endpoint your frontend can hit, and then it's up to the server and DB to delete the data from the source.
3

In React, you generally want to try avoiding direct DOM manipulation, since this takes state management out of React, which is something you want to avoid.

Therefore, instead of trying to delete each row directly using DOM functions like remove or removeChild, it would be best to keep all of the table rows in a key in the state object. Then, you can filter out the deleted row by filtering it out by index or through some other identifier. Here's an example:

import { Component } from 'react'
import './styles.css'

export default class App extends Component {
  state = {
    rows: [
      { id: 1, col1: 'A', col2: 'some text' },
      { id: 2, col1: 'B', col2: 'some text' }
    ]
  }

  spliceRow = (index) => {
    this.state.rows.splice(index, 1)
    this.setState({ rows: this.state.rows })
  }

  filterRows = (id) => {
    this.setState({
      rows: this.state.rows.filter((row) => {
        return row.id !== id
      })
    })
  }

  render() {
    return (
      <table className="App">
        <tbody>
          {this.state.rows.map((row, index) => {
            return (
              <tr key={row.id}>
                <td>{row.col1}</td>
                <td>{row.col2}</td>
                <td>
                  <button onClick={() => this.spliceRow(index)}>
                    Remove row with splice
                  </button>
                </td>
                <td>
                  <button onClick={() => this.filterRows(row.id)}>
                    Remove row with filter
                  </button>
                </td>
              </tr>
            )
          })}
        </tbody>
      </table>
    )
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.