簡體   English   中英

刪除子組件中的項目后重新渲染列表

[英]Re-render List after deleting item in child component

我想為博客構建儀表板。 我有一個頁面,使用每個列表項的組件列出所有博客文章。 現在,在每個列表項中,我都有一個刪除帖子的按鈕。 到目前為止,一切正常。 帖子被刪除,如果我重新加載頁面,它就會從列表中消失。 但是在刪除帖子后,我無法讓它自動重新呈現頁面。 我在這里使用window.location.reload()被騙了,但必須有更好的方法嗎?

這是我建立所有帖子列表的頁面

import {
  CCol,
  CContainer,
  CRow,
  CTable,
  CTableHead,
  CTableRow,
  CTableHeaderCell,
  CTableBody,
} from "@coreui/react";
import { useState, useEffect } from "react";
import DashboardSidebar from "../../components/dashboard/Sidebar";
import { getAllBlogPosts } from "../../services/blogService";
import BlogListItem from "../../components/dashboard/blog/BlogListItem";
import "./Dashboard.scss";

const AdminBlogListView = () => {
  const [blogposts, setBlogposts] = useState([]);

  useEffect(() => {
    getBlogPosts();
  }, []);

  async function getBlogPosts() {
    const response = await getAllBlogPosts();
    setBlogposts(response.data);
  }
  // console.log(blogposts);
  return (
    <div className="adminContainer">
      <div className="adminSidebar">
        <DashboardSidebar />
      </div>
      <div className="adminContent">
        <CContainer fluid>
          <CRow className="mb-3">
            <CCol>
              <CTable>
                <CTableHead>
                  <CTableRow>
                    <CTableHeaderCell scope="col">#</CTableHeaderCell>
                    <CTableHeaderCell scope="col">Titel</CTableHeaderCell>
                    <CTableHeaderCell scope="col">Content</CTableHeaderCell>
                    <CTableHeaderCell scope="col"></CTableHeaderCell>
                  </CTableRow>
                </CTableHead>
                <CTableBody>
                  {blogposts.map((post) => {
                    return <BlogListItem key={post._id} post={post} />;
                  })}
                </CTableBody>
              </CTable>
            </CCol>
          </CRow>
        </CContainer>
      </div>
    </div>
  );
};

export default AdminBlogListView;

這是 BlogListItem 組件

import { useState, useEffect } from "react";
import {
  CTableRow,
  CTableHeaderCell,
  CTableDataCell,
} from "@coreui/react";
import CIcon from "@coreui/icons-react";
import * as icon from "@coreui/icons";
import {
  deleteBlogPost,
  getBlogPostById,
  // updateBlogPost,
} from "../../../services/blogService";
import { useNavigate } from "react-router-dom";

const BlogListItem = (props) => {
  const id = props.post._id;
  const [visible, setVisible] = useState(false);
  const [post, setPost] = useState({
    title: "",
    content: "",
  });

  useEffect(() => {
    getBlogPostById(id)
      .then((response) => setPost(response.data))
      .catch((error) => console.log(error));
  }, []);

  const handleDelete = async (event) => {
    event.preventDefault();
    const choice = window.confirm("Are you sure you want to delete this post?");
    if (!choice) return;
    await deleteBlogPost(post._id);
    window.location.reload();
  };

  return (
    <>
      <CTableRow>
        <CTableHeaderCell scope="row">1</CTableHeaderCell>
        <CTableDataCell>{post.title}</CTableDataCell>
        <CTableDataCell>{post.content}</CTableDataCell>
        <CTableDataCell>
          <CIcon
            icon={icon.cilPencil}
            size="lg"
            onClick={() => setVisible(!visible)}
          />
          <CIcon
            icon={icon.cilTrash}
            className="deleteButton"
            size="lg"
            color=""
            onClick={handleDelete}
          />
        </CTableDataCell>
      </CTableRow>
    </>
  );
};

export default BlogListItem;

刪除項目后,我可以做什么而不是window.location.reload()來呈現AdminBlogListView 我嘗試使用useNavigate()但這沒有任何作用

提前致謝:)

您可以將 function 的引用從父組件AdminBlogListView到子組件BlogListItem ,以便在刪除博客文章時調用它。 function 將具有重新填充博客文章或手動將其從數據中刪除的效果(該實現位取決於您)。

解決方案 1:在刪除時重新填充所有博客文章

這是一個帶有一點代碼味道的快速修復(因為您實際上是在查詢服務器兩次:一次是刪除帖子,另一次是再次獲取帖子)。 然而,這是一種逃生艙類型的情況,並且易於實施。

當你渲染BlogListItem時,我們可以傳遞一個 function,比如onDelete ,它會調用getBlogPosts()從你的服務器手動重新填充博客文章:

<BlogListItem key={post._id} post={post} onDelete={getBlogPosts} />

然后是確保BlogListItem在刪除博客文章時調用onDelete()的問題:

const handleDelete = async (event) => {
  event.preventDefault();
  const choice = window.confirm("Are you sure you want to delete this post?");
  if (!choice) return;
  await deleteBlogPost(post._id);
  
  // Invoke the passed in `onDelete` function in component props
  props.onDelete();
};

解決方案 2:在父項中按 ID 刪除特定博客文章

與上述解決方案類似,但請確保您從父級傳遞 function ,該父級可以通過特定 ID 刪除帖子(來自參數)。 這為您節省了前往服務器的額外行程。

在您的組件AdminBlogListView中,定義一個 function ,它可以通過按 ID 刪除博客文章來改變blogposts state。 這可以通過利用功能更新來完成:

const onDelete = (id) => {
  setBlogposts((currentBlogPosts) => {
    const foundBlogPostIndex = currentBlogPosts.findIndex(entry => entry._id === id);
    
    // If we find the blog post with matching ID, remove it
    if (foundBlogPostIndex !== -1) currentBlogPosts.splice(foundBlogPostIndex, 1);

    return currentBlogPosts;
  })
}

注意:上面的代碼假定博客文章 ID 存儲在_id鍵中。 我只是從您的代碼中推斷出這一點,因為您沒有共享數據的形狀。

然后在您的BlogListItem組件中,它與解決方案 #1 的邏輯相同,但您需要在調用它時將 ID 傳遞給它:

const handleDelete = async (event) => {
  event.preventDefault();
  const choice = window.confirm("Are you sure you want to delete this post?");
  if (!choice) return;
  await deleteBlogPost(post._id);
  
  // Invoke the passed in `onDelete` function in component props with post ID as an argument
  props.onDelete(post._id);
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM