Home > Enterprise >  Delete row from React table with express and axios
Delete row from React table with express and axios

Time:07-27

I have a backend server running on localhost:3001 concurrently with frontend on localhost:3000 . I have created a table in React and populated it with data from the backend endpoint localhost:3001/food.

Now I'm trying to implement functionality for the delete buttons in my table which should delete the row on the frontend and row in the database based on the id. When the delete button is clicked, it opens a modal which has a confirm delete button. Once that is clicked, the id of the row is passed to a function.

I'm not sure how to call the express function in the backend that does the deletion query to the database now. Do I do this directly in my index.js file or work in the axios one? I'm very new with React so I'd appreciate some help with this!

This is my table in index.js file (I omitted some unnecessary code for it):

const DataTable = () => {
  return (
    <>
      <table>
        <tbody>
          {mapCriterias.map(item => {
            return (
              <tr key={item.id}>
                <td>{ item.id }</td>
                <td>{ item.food }</td>
                <td>{ renderDeleteButton(item.id) }</td>
              </tr>
            )
        </tbody>
      </table>
    </>
  )
}

My renderDeleteButton (also in index.js):

const renderDeleteButton = (key) => {
  let dialogEl=null;

  const delete_question = () => {
    // this is where my implementation would go
  }

  return (
    <>
      // modal
      <dialog ref={(el) => {
        dialogEl = el;
      }}>

        <div role="document">
          <h2>Are you sure you would like to delete this food?</h2>
          <p>This action cannot be undone</p>
          <form method="dialog">
            <div>
              <div>
                <button type="reset" onClick={()=>dialogEl.close()}>Cancel</button>
              </div>
              <div>
                <button type="del" id="delete_bottom" onClick {()=>delete_question()}>Delete</button>
              </div>
            </div>
          </form>
        </div>
      </dialog> 

      // delete button
      <button onClick={() =>dialogEl.showModal()} className="delete-btn">
        <span role="img">
          <Icon icon="gg:trash-empty"/>
        </span>
      </button>
    </>
  )

My fetch_db.js file:

const express = require('express');
const router = express.Router();
const pool = require('../credentials');

router.get('/', (req, res) =>{
  pool.query('SELECT * FROM Food', (error, results) => {
    if (error) {
      console.log(error)
      res.status(500).send('Error')
    } else {
      res.status(200).send(results.rows)
    }
  })
});

router.delete('/:foodid', (req, res) => {
  pool.query('DELETE FROM Criteria WHERE foodid=$1', [req.params.foodid], (error, results) => {
  if (error) {
    console.log(error)
    res.status(500).send('Error')
  } else {
    res.status(200).send('Success')
  }
});

My axios file that I use to fetch data from the db to populate my table:

import axios from "axios"

axios.defaults.baseURL = "http://localhost:3001"

export const getFoodData = () => {
  console.log("retrieved data");
  return axios.get("/food");
}

CodePudding user response:

Because your delete route is set up with this...

router.delete('/:foodid', ...

You need to send a DELETE request to /food/<id> then once that resolves successfully, remove the item from mapCriterias and close the modal.

For example

// note the `async`
const delete_question = async () => {
  try {
    await axios.delete(`http://localhost:3001/food/${encodeURIComponent(key)}`);
    // now remove the item from your state array
    // assuming you're using `useState`
    setMapCriterias((prev) => prev.filter(({ id }) => id !== key));

    dialogEl?.close(); // close the modal
  } catch (err) {
    console.error("delete_question", err.toJSON());
    // now show an error to the user or something ¯\_(ツ)_/¯
  }
};

CodePudding user response:

You can use onClick={() => delete_question((prevValue) => !prevValue)} in your button. You also need to make some changes in the file or query where you defined the delete_question param.

CodePudding user response:

Since you are keeping your axios routes separate, just add another route similar to the GET, just with either a POST or DELETE request, like so:

export const deleteFoodItem = (id) => {
  console.log("deleting data");
  return axios.post(`/food:${id}`);
}

And then in your renderDeleteButton component, import it and use it like:

import {deleteFoodItem} from "../axiosfilepath";

<button onClick={()=> deleteFoodItem(id)}>Delete button</button>

Just a couple notes about React:

You should name your components with PascalCase.

You don't need to use fragments (<></>) unless you don't wrap all elements in some container/wrapper.

(Might be preferential, but I find it simpler than using refs) You can keep modals really simple by toggling the modal with a const [modalOpen, setModal] = useState(false) and then inside the modal component setting display: none when false.

  • Related