简体   繁体   中英

How to delete data from database by using React js and REST API

I am learning REST API. I am using the react app for front end and backend for Node js and express server. For API I am using REST API. I am using MongoDB for the database. I successfully display all the data to the browser. I can able to search the data. Now I want to delete the data. I don't know how to delete data from REST API endpoint. I will be really glad if someone help me out. I tested my backend by using Postman. Everything works fine as expected.

This is my backend delete end point

app.delete("/students/:id", async (req, res, next) => {
  const id = req.params.id;

  try {
    student
      .remove({ _id: id })
      .exec()
      .then(data => {
        res.json(data);
      });
  } catch (error) {
    console.log(error);
  }
});

I export my API END points to React js

 export async function deleteStudent(id) {
  const response = await fetch(`/students/${id}`, {
    method: "DELETE"
  });
  return response.json();
}

This is the main component where I want to delete the data

 import React, { useState, useEffect } from "react";
import { logEntry } from "../Api/Api";
import { deleteStudent } from "../Api/Api";

function Datatable() {
  const [total, settotal] = useState([]);
  const [searchItem, setsearchItem] = useState({
    item: ""
  });
  const [data, setdata] = useState([]);

  const handleChange = e => {
    setsearchItem({ item: e.target.value });
  };

  const getEntries = async () => {
    const logEntries = await logEntry();

    console.log(logEntries);
    settotal(logEntries.count);
    setdata(logEntries.students);
  };

  const nameFilter = data.filter(list => {
    return list.name.toLowerCase().includes(searchItem.item.toLowerCase());
  });

  const deleteData = async id => {
    await deleteStudent(id);
  };

  useEffect(() => {
    getEntries();
  }, []);
  return (
    <div>
      <div style={{ paddingLeft: "800px" }}>
        <input
          placeholder="Search student"
          onChange={handleChange}
          style={{ width: "200px", height: "30px" }}
        />
      </div>
      <p>Total student: {total} </p>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>City</th>
            <th>Address</th>
            <th>Phone</th>
            <th>Email</th>
          </tr>
        </thead>

        <tbody>
          {nameFilter === "" ? (
            <p>Student not found</p>
          ) : (
            nameFilter.map(list => {
              return (
                <tr>
                  <td>{list.name}</td>
                  <td>{list.city}</td>
                  <td>{list.address}</td>
                  <td>{list.phone}</td>
                  <td>{list.email}</td>
                  <td>
                    <a
                      className="waves-effect red btn-small"
                      onClick={() => deleteData(list.id)}
                    >
                      Delete
                    </a>
                  </td>
                </tr>
              );
            })
          )}
        </tbody>
      </table>
    </div>
  );
}

export default Datatable;

I don't know, Am I doing?

This looks like a great start! I'm operating on the understanding that you need to somehow pass the id of the student you want to delete into the URL in deleteStudent() from the 'DELETE' button in your <DataTable> component.

So, first, let's refactor your deleteStudent() function:

export async function deleteStudent(id) {
  const response = await fetch(`/students/${id}`, {
    method: "DELETE",
  });
  return response.json();
}

You don't need to send any data with a DELETE request, you just need to hit the correct URL based on the id , which we can pass in to the method and dynamically include in the fetch() call.

Now, you need to find some way to pass that id into the deleteStudent() function. From what I can see, you are pulling in the student data here (I've paraphrased this):

const getEntries = async () => {

    // students are pulled in, I'm assuming they have an 'id' property that corresponds to the 'id' that MongoDB has them stored under
    const logEntries = await logEntry();

    // and now data references the students
    setdata(logEntries.students);

  };

It looks like then you filter the students here:

const nameFilter = data.filter(list => {
  return list.name.toLowerCase().includes(searchItem.item.toLowerCase());
});

And then render the filtered students with a call to .map(). This is where you can pass the id along in the onClick handler, assuming that you DO have an id field on these list elements. If you don't, then you will need to find a way to add the id in to this data:

nameFilter.map(list => {
  return (
    <tr>
      <td>{list.name}</td>
      <td>{list.city}</td>
      <td>{list.address}</td>
      <td>{list.phone}</td>
      <td>{list.email}</td>
      <td>
        <a
          className="waves-effect red btn-small"
          onClick={() => deleteData(list.id)} // this is where the id should get passed on to the handler, and then dynamically included in the DELETE /students/:id url
        >
          Delete
        </a>
      </td>
    </tr>
  );
})

Then, in your deleteData() function, you will receive the id as a param, and you can call your deleteStudent(id) function to make the request to the backend:

const deleteData = async id => {
  await deleteStudent(id);
};

There are some other things that need work, but you have the general idea correct! I'll give some hints towards further improvements below.

Do these need to be separate, or can they be combined?

import { logEntry } from "../Api/Api";
import { deleteStudent } from "../Api/Api";

Maybe clean up the DELETE route-handler:

app.delete("/students/:id", async (req, res, next) => {

  const id = req.params.id;

  try {
    // generally, Mongoose Model's are represented with TitleCase
    Student
      .remove({ _id: id })
      .exec() // is this needed? https://mongoosejs.com/docs/api/model.html#model_Model-remove
      .then(data => {
        res.json(data);
      });
  } catch (error) {
    console.log(error);
  }
});

There seems to be some extra state/hooks lying around in this Datatable:

function Datatable() {

  // ... bunch of code

  // do you need state for this?
  const [removeStudent, setremoveStudent] = useState([]);

  // ... more code

  const getEntries = async () => {

    // ... 

    setremoveStudent(deleteData); // not sure this is needed...
  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM