Search code examples
reactjsuse-effect

React refresh the page after delete button


The delete function of my app is working fine, however it requires the user to manually refresh the page after the user click the delete button in order to see the new list of elements in my database. I would like to automatically refresh after the click event. I am using react hooks for this projects. However, I found one solution if I remove useEffect's [] but in my backend it shows, its requesting crazily. I don't know, is it wise to remove useffect's [ ]?

Here is the component where it fetches data from backend and passes the props to another component

 import React, { useState, useEffect } from "react";
    import axios from "axios";
    import Table from "../Table/Table";
    import "./Display.css";
    const Display = () => {
      const [state, setState] = useState({ students: [], count: "" });
      const [searchItem, setsearchItem] = useState({
        item: ""
      });

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

      useEffect(() => {
        axios
          .get("/students")
          .then(response => {
            setState({
              students: response.data.students,
              count: response.data.count
            });
          })
          .catch(function(error) {
            console.log(error);
          });
      }, []); //If I remove this square brackets, it works 
      const nameFilter = state.students.filter(list => {
        return list.name.toLowerCase().includes(searchItem.item.toLowerCase());
      });

      return (
        <div>
          <h3 align="center">Student tables</h3>
          <p align="center">Total students: {state.count}</p>
          <div className="input-body">
            <div className="row">
              <div className="input-field col s6">
                <input placeholder="search student" onChange={Search} />
              </div>
            </div>
          </div>

          <table className="table table-striped">
            <thead>
              <tr>
                <th>Name</th>
                <th>Date of birth</th>
                <th>Address</th>
                <th>Zipcode</th>
                <th>City</th>
                <th>Phone</th>
                <th>Email</th>
                <th colSpan="2">Action</th>
              </tr>
            </thead>
            {nameFilter.map((object, index) => {
              return (
                <tbody key={index}>
                  <Table obj={object} /> //In here I am passing the props to the another component.
                </tbody>
              );
            })}
          </table>
        </div>
      );
    };

    export default Display;

This is second component which receives the props.

import React, { useState } from "react";
import { Link } from "react-router-dom";
import axios from "axios";

const Table = props => {
  const removeData = () => {
    axios
      .delete("/students/" + props.obj.id)
      .then(console.log("Deleted"))
      .catch(err => console.log(err));
  };

  return (
    <React.Fragment>
      <tr>
        <td>{props.obj.name}</td>
        <td>{props.obj.birthday}</td>
        <td>{props.obj.address}</td>
        <td>{props.obj.zipcode}</td>
        <td>{props.obj.city}</td>
        <td>{props.obj.phone}</td>
        <td>{props.obj.email}</td>
        <td>
          <Link
            to={"/edit/" + props.obj.id}
            className="waves-effect waves-light btn"
          >
            Edit
          </Link>
        </td>
        <td>
          <button onClick={removeData} className="waves-effect red btn ">
            Remove
          </button>
        </td>
      </tr>
    </React.Fragment>
  );
};

export default Table;

Solution

  • The [] in the useEffect hook is a dependency array to trigger the effect to run. If you want to trigger the effect (without it going off mercilessly), you can create a new variable that triggers that effect to run.

    import React, { useState, useEffect } from "react";
    import axios from "axios";
    import Table from "../Table/Table";
    import "./Display.css";
    
    const Display = () => {
      const [state, setState] = useState({ students: [], count: "" });
      const [requestData, setRequestData] = useState(new Date());
      const [searchItem, setsearchItem] = useState({
        item: ""
      });
    
      const Search = e => {
        setsearchItem({ item: e.target.value });
      };
    
      useEffect(() => {
        axios
          .get("/students")
          .then(response => {
            setState({
              students: response.data.students,
              count: response.data.count
            });
          })
          .catch(function(error) {
            console.log(error);
          });
      }, [requestData]);
    
      const nameFilter = state.students.filter(list => {
        return list.name.toLowerCase().includes(searchItem.item.toLowerCase());
      });
    
      return (
        <div>
          <h3 align="center">Student tables</h3>
            <p align="center">Total students: {state.count}</p>
            <div className="input-body">
              <div className="row">
                <div className="input-field col s6">
                  <input placeholder="search student" onChange={Search} />
                </div>
              </div>
            </div>
            <table className="table table-striped">
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Date of birth</th>
                  <th>Address</th>
                  <th>Zipcode</th>
                  <th>City</th>
                  <th>Phone</th>
                  <th>Email</th>
                  <th colSpan="2">Action</th>
                </tr>
              </thead>
              {nameFilter.map((object, index) => {
                return (
                  <tbody key={index}>
                    <Table obj={object} setRequestData={setRequestData} />
                  </tbody>
                );
              })}
            </table>
          </div>
        );
      };
    
    export default Display;
    

    Then you can trigger it from your Table component:

    import React, { useState } from "react";
    import { Link } from "react-router-dom";
    import axios from "axios";
    
    const Table = props => {
      const removeData = () => {
        axios
          .delete("/students/" + props.obj.id)
          .then(() => {
            props.setRequestData(new Date());
          })
          .catch(err => console.log(err));
      };
    
      return (
        <React.Fragment>
          <tr>
            <td>{props.obj.name}</td>
            <td>{props.obj.birthday}</td>
            <td>{props.obj.address}</td>
            <td>{props.obj.zipcode}</td>
            <td>{props.obj.city}</td>
            <td>{props.obj.phone}</td>
            <td>{props.obj.email}</td>
            <td>
              <Link
                to={"/edit/" + props.obj.id}
                className="waves-effect waves-light btn"
              >
                Edit
              </Link>
            </td>
            <td>
              <button onClick={removeData} className="waves-effect red btn ">
                Remove
              </button>
            </td>
          </tr>
        </React.Fragment>
      );
    };
    
    export default Table;