Redux News Reader stuck on step 10

Currently the comments are not loading for the articles. My code is below. Not sure what I am missing.

commentSlice.js

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
// Create loadCommentsForArticleId here.
export const loadCommentsForArticleId = createAsyncThunk(
  'comments/loadCommentsForArticleId',
  async (id) => {
    const response = await fetch(`api/articles/${id}/comments`)
    const json = await response.json()
    return json
  }
)
// Create postCommentForArticleId here.

export const commentsSlice = createSlice({
  name: 'comments',
  initialState: {
    // Add initial state properties here.
    byArticleId: {},
    isLoadingComments: false,
    failedToLoadComments: false
  },
  // Add extraReducers here.
  extraReducers: {
    [loadCommentsForArticleId.pending]: (state, action) => {
      state.isLoadingComments = true
      state.failedToLoadComments = false
    },
    [loadCommentsForArticleId.fulfilled]: (state, action) => {
      state.byArticleId = {[action.payload.articleId]: action.payload.comments};
      state.isLoadingComments = false
      state.failedToLoadComments = false
    },
    [loadCommentsForArticleId.rejected]: (state, action) => {
      state.isLoadingComments = false
      state.failedToLoadComments = true
    }
  }
});

export const selectComments = (state) => state.comments.byArticleId;
export const isLoadingComments = (state) => state.comments.isLoadingComments;
export const createCommentIsPending = (state) => state.comments.createCommentIsPending;

export default commentsSlice.reducer;

Comments.js

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
  loadCommentsForArticleId,
  selectComments,
  isLoadingComments,
} from '../comments/commentsSlice';
import { selectCurrentArticle } from '../currentArticle/currentArticleSlice';
import CommentList from '../../components/CommentList';
import CommentForm from '../../components/CommentForm';

const Comments = () => {
  const dispatch = useDispatch();
  const article = useSelector(selectCurrentArticle);
  // Declare additional selected data here.
  const comments = useSelector(selectComments);
  const commentsAreLoading = useSelector(isLoadingComments);

  // Dispatch loadCommentsForArticleId with useEffect here.
  useEffect(() => {
    if (article !== undefined) {
      dispatch(loadCommentsForArticleId(article.id))
    }
  }, [dispatch, article])

  const commentsForArticleId = article ? comments[article.id] : []

  if (commentsAreLoading) return <div>Loading Comments</div>;
  if (!article) return null;

  return (
    <div className='comments-container'>
      <h3 className='comments-title'>Comments</h3>
      <CommentList comments={commentsForArticleId} />
      <CommentForm articleId={article.id} />
    </div>
  );
};

export default Comments;

CommentList.js

import React from 'react';
import Comment from './Comment';

export default function CommentList({ comments }) {
  if (!comments) {
    return null;
  }
  
  return (
    <ul className='comments-list'>
      {
        comments.map(comment => {
          <Comment comment={comment} />
        })
      }
    </ul>
  );
}

Note: Haven’t changed CommentForm.js since I haven’t got to that part yet.

Things you can do to trace the error:

  1. Check several articles: Not all articles have comments in the first place
  2. Change the hard coded stuff: I experienced that the code wasn’t always compiled on save.
  3. Open the browser console and log the article id parameter and the comments in loadCommentsForArticleId
2 Likes

Haven’t done this project, but during a very quick skim of your code, CommentList.js caught my eye (there may be other issues).

// You wrote:
comments.map(comment => {
          <Comment comment={comment} />
})

Since you are using curly braces for the body of the arrow function, so you either need to do an explicit return OR remove the curly braces and do an implicit return.

// Explicit return
comments.map(comment => {
          return <Comment comment={comment} />
})

// Implicit return
comments.map(comment => <Comment comment={comment} /> )
1 Like

That worked. Thanks.

1 Like