NextJS创建新Post后无法显示,如何更新ListOfPosts组件?
解决创建新帖子后列表不更新的问题
问题根源
- jsonplaceholder的模拟特性:它的POST请求仅返回模拟数据,不会真正将新帖子存入后端,因此重新调用GET接口也获取不到刚创建的帖子。
- 组件状态隔离:
NewPost和ListOfPosts的状态各自独立,创建新帖子后没有通知列表组件更新数据。
解决方案
通过状态提升将帖子列表的状态管理移到父组件PostsPage中,让NewPost创建帖子后直接更新父组件的状态,实现列表实时显示新内容。
1. 修改父组件 posts/page.jsx
把帖子状态和初始化获取逻辑移到父组件,同时给子组件传递状态更新的回调和帖子数据:
'use client' import { useEffect, useState } from "react"; import ListOfPosts from "./ListOfPosts"; import NewPost from "./NewPost"; import axios from "axios"; export default function PostsPage() { const [posts, setPosts] = useState([]); // 初始化获取帖子列表 useEffect(() => { const fetchPosts = async () => { try { const response = await axios.get('https://jsonplaceholder.typicode.com/posts'); setPosts(response.data); } catch (error) { console.log(error); } }; fetchPosts(); }, []); // 处理新帖子创建后的状态更新 const handlePostCreated = (newPost) => { // 将新帖子添加到列表顶部 setPosts(prevPosts => [newPost, ...prevPosts]); }; return ( <> <section> <NewPost onPostCreated={handlePostCreated} /> <ListOfPosts posts={posts} /> </section> </> ); }
2. 修改 NewPost.jsx
让addPost返回模拟的新帖子数据,调用父组件传递的回调通知状态更新:
'use client' import React, { useState } from 'react'; import axios from 'axios'; async function addPost(title, body, userId) { try { const response = await axios.post('https://jsonplaceholder.typicode.com/posts', { title, body, userId, }); return response.data; // 返回模拟的新帖子数据 } catch (error) { console.error('Error creating post:', error); return null; } } function NewPost({ onPostCreated }) { const [title, setTitle] = useState(''); const [body, setBody] = useState(''); const [userId, setUserId] = useState(1); const handleSubmit = async (e) => { e.preventDefault(); const newPost = await addPost(title, body, userId); if (newPost) { onPostCreated(newPost); // 通知父组件更新列表 } // 重置表单 setTitle(''); setBody(''); }; return ( <div> <h2>Create New Post</h2> <form onSubmit={handleSubmit}> <div> <label htmlFor="title">Title:</label> <input name="title" type="text" id="title" value={title} onChange={(e) => setTitle(e.target.value)} required className='text-red-500' /> </div> <div> <label htmlFor="body">Body:</label> <input type="text" id="body" value={body} onChange={(e) => setBody(e.target.value)} required className='text-red-500' /> </div> <button type="submit">Create Post</button> </form> </div> ); } export default NewPost;
3. 修改 ListOfPosts.jsx
不再自行管理状态,直接使用父组件传递的posts数据:
'use client' import Link from "next/link"; export default function ListOfPosts({ posts }) { return posts.map(post => ( <Link href={`/posts/${post.id}`} key={post.id}> <article> <h2 style={{color: '#09f'}}>{post.id} {post.title}</h2> <p>{post.body}</p> </article> </Link> )) }
补充说明
- 针对jsonplaceholder的模拟特性,我们直接将返回的模拟新帖子添加到前端列表,实现实时显示。
- 如果是真实后端API,可在
handlePostCreated中重新调用fetchPosts函数,从后端拉取最新的帖子列表,确保数据一致性。
内容的提问来源于stack exchange,提问作者tukitooo1998
相关产品推荐
相关产品推荐

