I have a MERN app that allows logged in user to create posts, with text and images. When the post is created the component re-renders and the post is adde automatically. The images and text from the post show up right but the username and user's picture don't show up unless I refresh the page.
This is the posts page:
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;
Here is the individual post component:
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;
Here is the 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);
}
};
This is the postRequest function:
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);
}
};
Here is the post request part of the 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 };
I got this answer from another user but then his post was deleted and his profile suspended for a few days. I watied to see if his post would show up, but it has not, so here is the answer. On the posts.js page in the userEffect, I added post?.length and that fiexd the issue.
useEffect(() => {
dispatch(getTimeLinePosts(userId));
}, [dispatch, userId, posts?.length]);
Now when I create a post the user's name and image show up.