[英]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 將具有重新填充博客文章或手動將其從數據中刪除的效果(該實現位取決於您)。
這是一個帶有一點代碼味道的快速修復(因為您實際上是在查詢服務器兩次:一次是刪除帖子,另一次是再次獲取帖子)。 然而,這是一種逃生艙類型的情況,並且易於實施。
當你渲染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();
};
與上述解決方案類似,但請確保您從父級傳遞 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.