React Blog Page Not Loading & Comments Section Not Working

I am working on a React blog page where users can view blog posts and leave comments (similar to YouTube's comment section). However, after clicking on the blog page and clicking on a blog I wish to view the content no longer loads properly and is just stuck saying loading so the contents are no longer visible on the specified page and the comment section isn't visible either.

What I Tried & Expected Outcome:

  1. Fetching Blog Posts:

    • Used axios.get('http://127.0.0.1:8000/api/blogs/') inside useEffect().

    • I had Expected posts to load, but they do not appear.

  2. Deleting Blog Posts:

    • Used axios.delete(\http://127.0.0.1:8000/api/blogs/delete/$%7BblogId%7D/%5C%5C%5C%60, { headers: { Authorization: `Token ${user.token}` } })`.

    • Expected blog deletion to work, but encountered errors.

  3. Commenting System:

    • Implemented a comment section using axios.post() to submit new comments but nothing is being displayed at all its just stuck saying loading.

    • Expected comments to display but they do not appear.

Here's The backend snippet of the code im trying to run

@api_view(['GET', 'POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def blog_comments(request, blog_id):
    """
    GET /blogs/<blog_id>/comments/
    Returns: All comments for specified blog
    
    POST /blogs/<blog_id>/comments/
    Required data: content, parent (optional for replies)
    Returns: Created comment data
    Requires: Authentication Token
    """
    blog = get_object_or_404(Blog, id=blog_id)
    if request.method == 'GET':
        comments = Comment.objects.filter(blog=blog, parent=None)
        serializer = CommentSerializer(comments, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        serializer = CommentSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(blog=blog, author=request.user)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['DELETE'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_comment(request, comment_id):
    """
    DELETE /blogs/<blog_id>/comments/<comment_id>/
    Deletes specified comment if user is author
    Requires: Authentication Token
    Returns: 204 No Content on success
    """
    comment = get_object_or_404(Comment, id=comment_id)
    if comment.author != request.user:
        return Response({'detail': 'Permission denied'}, status=status.HTTP_403_FORBIDDEN)
    comment.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

Frontend

import React, { useState, useEffect, useContext } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import { UserContext } from '../../context/UserContext';

const BlogPost = () => {
    const { id } = useParams();
    const [blog, setBlog] = useState(null);
    const [comments, setComments] = useState([]);
    const [newComment, setNewComment] = useState('');
    const { user } = useContext(UserContext);

    useEffect(() => {
        fetchBlogPost();
    }, []);

    const fetchBlogPost = async () => {
        try {
            const [blogResponse, commentsResponse] = await Promise.all([
                axios.get(`http://127.0.0.1:8000/api/blogs/${id}/`),
                axios.get(`http://127.0.0.1:8000/api/blogs/${id}/comments/`, {
                    headers: user ? { 'Authorization': `Token ${user.token}` } : {}
                })
            ]);
            setBlog(blogResponse.data);
            setComments(commentsResponse.data || []);
        } catch (error) {
            console.error('Error fetching blog post:', error);
        }
    };

    const handleCommentSubmit = async (e) => {
        e.preventDefault();
        if (!user) {
            alert("You must be logged in to comment.");
            return;
        }

        try {
            const response = await axios.post(
                `http://127.0.0.1:8000/api/blogs/${id}/comments/`,
                { content: newComment },
                { headers: { 'Authorization': `Token ${user.token}` } }
            );
            setComments([response.data, ...comments]);
            setNewComment('');
        } catch (error) {
            console.error('Error posting comment:', error);
        }
    };

    const handleDeleteComment = async (commentId) => {
        try {
            await axios.delete(
                `http://127.0.0.1:8000/api/blogs/${id}/comments/${commentId}/`,
                { headers: { 'Authorization': `Token ${user.token}` } }
            );
            setComments(comments.filter(comment => comment.id !== commentId));
        } catch (error) {
            console.error('Error deleting comment:', error);
        }
    };

    if (!blog) return <div>Loading...</div>;

    return (
        <div>
            <h1>{blog.title}</h1>
            <p>{blog.content}</p>

            <div className="comments-section">
                <h3>Comments</h3>
                {user && (
                    <form onSubmit={handleCommentSubmit}>
                        <textarea 
                            value={newComment} 
                            onChange={(e) => setNewComment(e.target.value)}
                            placeholder="Add a public comment..."
                            required
                        />
                        <button type="submit">Comment</button>
                    </form>
                )}

                {comments.length > 0 ? (
                    comments.map((comment) => (
                        <div key={comment.id} className="comment">
                            <p><strong>{comment.author}</strong>: {comment.content}</p>
                            <button onClick={() => handleDeleteComment(comment.id)}>Delete</button>
                        </div>
                    ))
                ) : (
                    <p>No comments yet.</p>
                )}
            </div>
        </div>
    );
};

export default BlogPost;

api - urls.py

from django.urls import path
from .views import blog_comments, delete_comment

urlpatterns = [
    path('blogs/<int:blog_id>/comments/', blog_comments, name='blog_comments'),
    path('blogs/<int:blog_id>/comments/<int:comment_id>/', delete_comment, name='delete_comment'),
]
Вернуться на верх