Home > Back-end >  Reload updated Table once a column is removed
Reload updated Table once a column is removed

Time:02-05

this is a component that retrieve data from API and generate a table. One button in a column for removing the row opens a Modal.

enter image description here

For avoiding in first component render to trigger api.delete request, an useRef set as false in second useEffect

Modal's Delete button return row info in deleteHandler function which successfully trigger api.delete request on confirmation, remove user in backend however table is not reloading.

Once row is removed expected result is triggering api.get request and display table now updated and without row removed.

In order to get that result I tried with const [reload, setReload] = useState(false); state which introduce another dependency to both userEffect

reload state effectively reload table data updated however it cause also that api.delete request trigger with const ida undefined. Below component script it can find useEffect with my tried.

Any hint or possible solution is appreciated

import React, { Fragment, useEffect, useState, useRef } from "react";
... other imports ... 

export default function AllUsers() {
  const api = useApi();
  const [userData, setUserData] = useState();
  const [showModal, setShowModal] = useState(false);
  const navigate = useNavigate();
  const [modalMessage, setModalMessage] = useState();
  const [removeUserId, setRemoveUserId] = useState();
  const [ida, setIda] = useState();
  let effectRan = useRef(false);
  const [reload, setReload] = useState(false);

  useEffect(() => {
    (async () => {
      const response = await api.get("/admin/users");
      if (response.ok) {
        setUserData(response.body);
      } else {
        setUserData(null);
      }
    })();
  }, [api]);

  useEffect(() => {
    if (effectRan.current) {
      // console.log("effect run");

      (async () => {
        const response = await api.delete("/admin/users", {
          ida: ida,
        });
        if (response.ok && response.status === 204) {
          console.log(response);
        } else {
          console.log(response.body.errors);
        }
      })();
    }
    return () => (effectRan.current = true);
  }, [api, ida]);

  const handleEditClick = (e, rowIndex) => {
    // console.log("user/"   rowIndex.username);
    navigate("/user/"   rowIndex.username, [navigate]);
  };

  const handleRemoveClick = (e, rowIndex) => {
    // console.log([rowIndex]);
    setShowModal(true);

    setModalMessage({
      title: `Remove ${rowIndex.username}`,
      message: `User's email to remove ${rowIndex.email}`,
    });
    setRemoveUserId(rowIndex.id);
  };

  const closeHandler = () => {
    setShowModal(false);
  };

  const deleteHandler = () => {
    // console.log(removeUserId);
    setIda(removeUserId);
    setShowModal(false);
  };

  // console.log(ida, idb);

  return (
    <Fragment>
      {showModal && (
        <BtModal
          show={showModal}
          title={modalMessage.title}
          message={modalMessage.message}
          handleClose={closeHandler}
          onConfirm={deleteHandler}
        />
      )}
      <Body>
        <h1>User Table</h1>

        {userData === undefined ? (
          <Spinner animation="border" />
        ) : (
          <>
            {userData === null ? (
              <p>Could not retrieve users.</p>
            ) : userData.length === 0 ? (
              <p>There are not users in system</p>
            ) : (
              <UserListTable
                newData={userData}
                handleEditClick={handleEditClick}
                handleRemoveClick={handleRemoveClick}
              />
            )}
          </>
        )}
      </Body>
    </Fragment>
  );
}

useEffect updated with reload state:

 useEffect(() => {
    (async () => {
      const response = await api.get("/admin/users");
      if (response.ok) {
        setUserData(response.body);
        effectRan.current = false;
      } else {
        setUserData(null);
      }
    })();
  }, [api, reload]);

  useEffect(() => {
    if (effectRan.current) {
      // console.log("effect run");

      (async () => {
        const response = await api.delete("/admin/users", {
          ida: ida,
        });
        if (response.ok && response.status === 204) {
          console.log(response);
          setReload(!reload);
        } else {
          console.log(response.body.errors);
        }
      })();
    }
    return () => (effectRan.current = true);
  }, [api, ida, reload]);

CodePudding user response:

It looks like you're trying to delete an item in the table and confirm it via a prompt. I can see that you've used a lot of useEffects, which might be making things a bit complicated.

Don't worry though, I have a solution that should be much simpler. Let me show you what I mean!

const Page = () => {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState([]);
  const [deleting, setDeleting] = useState(false);
  
  const [selectedItem, setSelectedItem] = useState(null);

  const deleteHandler = async() => {
    setDeleting(true);
    await api.delete(selectedItem);

    // Next you can either update the state itself
    let tD = [...data];
    const index = tD.findIndex((i) => i.id == selectedItem);
    tD.splice(index, 1);
    setSelectedItem(tD);

    // or refetch data from the backend and update the state
    const d = await api.getData();
    setData(d);
    setDeleting(false);
    setSelectedItem(null);
  };

  useEffect(() => {
    const fetchData = async() => {
      setLoading(true);
      const d = await api.getData();
      setData(d);
      setLoading(false);
    }
    fetchData();
  }, [])

  return loading ? <div>Loading...</div> : <>
    {/*Other JSX elements*/}

    {selectedItem && <div>

      {/*prompt body*/}

      <button onClick={() => {setSelectedItem(null)}}>Cancel</button>
      <button disabled={deleting} onClick={() => {deleteHandler()}}>Delete</button>
      {/*Button will be disabled when the DELETE request is sent*/}
    </div>}

    {data.map((row) => {
      return <tr key={row.id}>
          <td>...</td>
          <td>...</td>
          <td>
            <button onClick={setSelectedItem(row.id)}>Delete</button>
          </td>
      </tr>
    })}
  </>
}

CodePudding user response:

Here you modify your last edit

 const deleteHandler = () => {
    // console.log(removeUserId);
    setIda(removeUserId);
    setReload(!reload)
    setShowModal(false);
  };
useEffect(() => {
    (async () => {
      const response = await api.get("/admin/users");
      if (response.ok) {
        setUserData(response.body);
      } else {
        setUserData(null);
      }
    })();
  }, [api]);


  useEffect(() => {
     effectRan.current = reload;
    if (effectRan.current) {
      // console.log("effect run");

      (async () => {
        const response = await api.delete("/admin/users", {
          ida: ida,
        });
        if (response.ok && response.status === 204) {
          console.log(response);
          setReload(!reload);
        } else {
          console.log(response.body.errors);
        }
      })();
    }
    return () => {
         effectRan.current = false;
        };
  }, [api, ida, reload]);
  • Related