MERN应用新发布帖子用户名与头像需刷新才显示问题
MERN栈帖子创建后用户名/头像需刷新才显示问题解决
问题描述
我开发了一个MERN栈应用,支持登录用户发布包含文本和图片的帖子。创建帖子后组件会重渲染,帖子自动添加,帖子的图片和文本可正常显示,但用户名和用户头像需刷新页面才能显示。
相关代码
帖子页面(Posts组件)
import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { getTimeLinePosts } from '../../../actions/postAction'; import Post from '../Post/Post.js'; import PulseLoader from 'react-spinners/FadeLoader'; const Posts = ({ user }) => { const dispatch = useDispatch(); const { posts, loading } = useSelector((state) => state.postReducer); console.log('user ID :', user.user._id); useEffect(() => { dispatch(getTimeLinePosts(user.user._id)); }, [dispatch, user.user._id]); return ( <div className="Posts"> {loading ? ( <div style={{ display: 'flex', justifyContent: 'center' }}> <PulseLoader color="#485639" height={15} width={5} loading={loading} /> </div> ) : posts && posts.length ? ( posts.map((post, i) => <Post key={i} post={post} index={i} />) ) : ( "You haven't shared anything yet." )} </div> ); }; export default Posts;
单个帖子组件(Post组件)
import Moment from 'react-moment'; import { Link } from 'react-router-dom'; import { Dots, Public } from '../../../svg'; import { useRef } from 'react'; import './style.css'; import { useSelector } from 'react-redux'; const Post = ({ post }) => { //const { user } = useSelector((state) => state.authReducer.authData); return ( <div className="post"> <div className="post_header"> <Link to={`/${post?.user.username}`} className="post_header_left"> <img src={post?.user.picture} alt="" /> <div className="header_col"> <div className="post_profile_name"> {post?.user.first_name} {post?.user?.last_name} <div className="updated_p"> {post.type === 'profilePicture' && 'updated their profile picture'} {post.type === 'cover' && 'updated their cover picture'} </div> </div> <div className="post_profile_privacy_date"> <Moment fromNow interval={30}> {post.createdAt} </Moment> . <Public color="#828387" /> </div> </div> </Link> <div className="post_header_right hover1"> <Dots color="#828387" /> </div> </div> <div className="post_text">{post.text}</div> {post.images && post.images.length && ( <div className={ post.images.length === 1 ? 'grid_1' : post.images.length === 2 ? 'grid_2' : post.images.length === 3 ? 'grid_3' : post.images.length === 4 ? 'grid_4' : post.images.length >= 5 && 'grid_5' } > {post.images.slice(0, 5).map((image, i) => ( <img src={image.url} key={i} alt="" className={`img-${i}`} /> ))} {post.images.length > 5 && ( <div className="more-pics-shadow">+{post.images.length - 5}</div> )} </div> )} </div> ); }; export default Post;
postController
exports.getTimelinePosts = async (req, res) => { const userId = req.params.id; try { const posts = await Post.find({ user: userId }).populate( 'user', 'username first_name last_name picture' ); res.status(200).json(posts); } catch (error) { res.status(500).json(error); } };
postRequest函数
export const getTimeLinePosts = (id, token) => async (dispatch) => { console.log(id); const API_URL = 'api/posts/'; dispatch({ type: 'RETREIVING_START' }); try { const { data } = await axios.get(API_URL + `${id}/timeline/`); dispatch({ type: 'RETREIVING_SUCCESS', data: data }); } catch (error) { dispatch({ type: 'RETREIVING_FAIL' }); console.log(error); } };
postReducer相关部分
case 'RETREIVING_START': return { ...state, loading: true, error: false }; case 'RETREIVING_SUCCESS': return { ...state, posts: action.data.reverse(), loading: false, error: false, }; case 'RETREIVING_FAIL': return { ...state, loading: false, error: true };
问题原因
创建帖子时,后端返回的新帖子数据未填充user关联字段(仅包含user ID),前端将这条未填充的数据加入Redux后,Post组件无法读取post.user.username、post.user.picture等信息;而刷新页面时调用getTimeLinePosts接口,后端会通过populate方法填充完整的user信息,因此能正常显示。
解决方法
1. 修改后端创建帖子接口,返回填充后的帖子数据
在创建帖子的controller中,保存帖子后执行populate操作,返回包含完整user信息的帖子:
exports.createPost = async (req, res) => { try { const newPost = new Post(req.body); const savedPost = await newPost.save(); // 填充user字段,获取需要的用户信息 const populatedPost = await Post.findById(savedPost._id).populate( 'user', 'username first_name last_name picture' ); res.status(200).json(populatedPost); } catch (error) { res.status(500).json(error); } };
2. 前端创建帖子后,将填充后的新帖子加入Redux
修改创建帖子的action,将后端返回的完整帖子数据添加到Redux的posts数组中:
export const createPost = (postData) => async (dispatch) => { try { const { data } = await axios.post('/api/posts', postData); // 将新帖子插入到posts数组开头,保证最新帖子显示在最前面 dispatch({ type: 'ADD_POST', payload: data }); } catch (error) { console.log(error); } };
3. 在postReducer中添加处理新帖子的case
// 新增ADD_POST case case 'ADD_POST': return { ...state, posts: [action.payload, ...state.posts] };
这样处理后,创建帖子时前端就能拿到包含完整用户信息的帖子数据,组件渲染时无需刷新即可显示用户名和头像。
内容的提问来源于stack exchange,提问作者Stephen Scott Moore
相关产品推荐
相关产品推荐

