Social Media Platform
Build a social media platform with posts, comments, user profiles, and real-time features. This is a foundational concept in component-based UI development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world React experience. Take your time with each section and practice the examples
Project Overview
Create a social media platform with user authentication, posts, comments, likes, user profiles, and real-time notifications.. This is an essential concept that every React developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Core Features
// Social media app features
- User authentication and profiles
- Create, edit, and delete posts
- Like and comment on posts
- Follow/unfollow users
- Real-time notifications
- News feed with infinite scroll
- User search and discovery
- Direct messaging
- Post sharing and bookmarking
// Main components structure
src/
├── components/
│ ├── auth/
│ │ ├── LoginModal.js
│ │ ├── RegisterModal.js
│ │ └── AuthGuard.js
│ ├── post/
│ │ ├── PostCard.js
│ │ ├── PostForm.js
│ │ ├── PostDetail.js
│ │ ├── CommentList.js
│ │ └── LikeButton.js
│ ├── profile/
│ │ ├── ProfileHeader.js
│ │ ├── ProfilePosts.js
│ │ ├── ProfileStats.js
│ │ └── EditProfile.js
│ ├── feed/
│ │ ├── NewsFeed.js
│ │ ├── FeedFilter.js
│ │ └── InfiniteScroll.js
│ └── common/
│ ├── Header.js
│ ├── Sidebar.js
│ ├── NotificationBell.js
│ └── SearchBar.js
├── hooks/
│ ├── usePosts.js
│ ├── useAuth.js
│ ├── useInfiniteScroll.js
│ └── useNotifications.js
├── context/
│ ├── AuthContext.js
│ ├── PostContext.js
│ └── NotificationContext.js
└── utils/
├── api.js
├── socket.js
└── helpers.jsReal-time Features
// Real-time features with WebSocket
import { useEffect, useState } from 'react';
import io from 'socket.io-client';
// WebSocket connection
const socket = io('http://localhost:3001');
// Real-time notifications
function useNotifications() {
const [notifications, setNotifications] = useState([]);
useEffect(() => {
socket.on('notification', (notification) => {
setNotifications(prev => [notification, ...prev]);
});
socket.on('like', (data) => {
// Handle real-time like updates
console.log('Post liked:', data);
});
socket.on('comment', (data) => {
// Handle real-time comment updates
console.log('New comment:', data);
});
return () => {
socket.off('notification');
socket.off('like');
socket.off('comment');
};
}, []);
return { notifications };
}
// Post management with real-time updates
function usePosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
// Listen for real-time post updates
socket.on('newPost', (post) => {
setPosts(prev => [post, ...prev]);
});
socket.on('postUpdate', (updatedPost) => {
setPosts(prev => prev.map(post =>
post.id === updatedPost.id ? updatedPost : post
));
});
socket.on('postDelete', (postId) => {
setPosts(prev => prev.filter(post => post.id !== postId));
});
return () => {
socket.off('newPost');
socket.off('postUpdate');
socket.off('postDelete');
};
}, []);
const createPost = async (postData) => {
setLoading(true);
try {
const response = await fetch('/api/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(postData),
});
const newPost = await response.json();
// Emit real-time update
socket.emit('createPost', newPost);
setPosts(prev => [newPost, ...prev]);
} catch (error) {
console.error('Error creating post:', error);
} finally {
setLoading(false);
}
};
const likePost = async (postId) => {
try {
await fetch(`/api/posts/${postId}/like`, { method: 'POST' });
socket.emit('likePost', { postId });
} catch (error) {
console.error('Error liking post:', error);
}
};
return { posts, loading, createPost, likePost };
}
// Post components
function PostCard({ post }) {
const { likePost } = usePosts();
const [liked, setLiked] = useState(post.liked);
const [likeCount, setLikeCount] = useState(post.likeCount);
const handleLike = async () => {
await likePost(post.id);
setLiked(!liked);
setLikeCount(prev => liked ? prev - 1 : prev + 1);
};
return (
<div className="post-card">
<div className="post-header">
<img src={post.author.avatar} alt={post.author.name} />
<div>
<h4>{post.author.name}</h4>
<span>{new Date(post.createdAt).toLocaleDateString()}</span>
</div>
</div>
<div className="post-content">
<p>{post.content}</p>
{post.image && <img src={post.image} alt="Post" />}
</div>
<div className="post-actions">
<button
onClick={handleLike}
className={`like-btn ${liked ? 'liked' : ''}`}
>
❤️ {likeCount}
</button>
<button className="comment-btn">💬 {post.commentCount}</button>
<button className="share-btn">📤 Share</button>
</div>
</div>
);
}
// Infinite scroll feed
function NewsFeed() {
const { posts, loading } = usePosts();
const [page, setPage] = useState(1);
const [hasMore, setHasMore] = useState(true);
const loadMorePosts = async () => {
if (loading || !hasMore) return;
try {
const response = await fetch(`/api/posts?page=${page + 1}`);
const newPosts = await response.json();
if (newPosts.length === 0) {
setHasMore(false);
} else {
setPosts(prev => [...prev, ...newPosts]);
setPage(prev => prev + 1);
}
} catch (error) {
console.error('Error loading more posts:', error);
}
};
useEffect(() => {
const handleScroll = () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 1000) {
loadMorePosts();
}
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [page, hasMore, loading]);
return (
<div className="news-feed">
{posts.map(post => (
<PostCard key={post.id} post={post} />
))}
{loading && <div className="loading">Loading more posts...</div>}
{!hasMore && <div className="end">No more posts to load</div>}
</div>
);
}