Redux News Reader Project

I am having some issues identifying the error in my code for this project. Currently I am unable to render anything onto the screen even though I have worked through all the steps. I would greatly appreciate some advice on this.

//commentSlice.js

// Import createAsyncThunk and createSlice here.
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

export const loadCommentsForArticleId = createAsyncThunk(
  "comments/loadCommentsForArticleId",
  async (id) => {
    const response = await fetch(`api/articles/${id}/comments`);
    const json = await response.json();
    return json;
  }
)
// Create loadCommentsForArticleId here.
export const postCommentForArticleId = createAsyncThunk(
  'comments/postCommentForArticleId',
  async ({articleId, comment}) => {
    const requestBody = JSON.stringify({comment: comment});
    const response = await fetch(`api/articles/${articleId}`, {
      method: 'POST',
      body: requestBody
    });
    const json = await response.json();

    return json;
  }
// Create postCommentForArticleId here.

export const commentsSlice = createSlice({
  name: 'comments',
  initialState: {
    byArticleId: {},
    isLoadingComments: false,
    failedToLoadComments: false,
    createCommentIsPending: false,
    failedToCreateComment: false
  },
extraReducers: (builder) => {
    builder
      .addCase(loadCommentsForArticleId.pending, (state) => {
        state.isLoadingComments = true;
        state.failedToLoadComments = false;
      })
      .addCase(loadCommentsForArticleId.fulfilled, (state, action) => {
        state.isLoadingComments = false;
        state.failedToLoadComments = false;
        state.byArticleId[action.payload.articleId] = action.payload.comments;
      })
      .addCase(loadCommentsForArticleId.rejected, (state, action) => {
        state.isLoadingComments = false;
        state.failedToLoadComments = true;
        state.byArticleId = {};
      })
      .addCase(postCommentForArticleId.pending, (state) => {
        state.createCommentIsPending = true;
        state.failedToCreateComment = false;
      })
      .addCase(postCommentForArticleId.fulfilled, (state, action) => {
        state.createCommentIsPending = false;
        state.failedToCreateComment = false;
        state.byArticleId[action.payload.articleId].push(action.payload);
      })
      .addCase(postCommentForArticleId.rejected, (state, action) => {
        state.createCommentIsPending = false;
        state.failedToCreateComment = 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) {
      dispatch(loadCommentsForArticleId(article.id));
    }
  }, [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>
  );
}

//CommentForm.js

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
  createCommentIsPending,
  postCommentForArticleId
} from '../features/comments/commentsSlice';

export default function CommentForm({ articleId }) {
  const dispatch = useDispatch();
  const [comment, setComment] = useState('');
  
  // Declare isCreatePending here.

  const handleSubmit = (e) => {
    e.preventDefault();
    // dispatch your asynchronous action here!
    dispatch(postCommentForArticleId({articleId, comment}));
    setComment('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <label for='comment' className='label'>
        Add Comment:
      </label>
      <div id='input-container'>
        <input
          id='comment'
          value={comment}
          onChange={(e) => setComment(e.currentTarget.value)}
          type='text'
        />
        <button
          
          className='comment-button'
        >
          Submit
        </button>
      </div>
    </form>
  );
}

Thanks for any help on this!

Hi @byte0115562031
I finished that project so maybe I am able to help. Just a few questions in order to get an idea where to look at:

  1. Are you working in the Codecademy environment or did you set up the project locally?
  2. Do you remember at which step nothing was rendered anymore?
  3. Are there any error messages in the browser’s console related to the project?

Hi @mirja_t ,

  1. I am working in the codeacademy environment for this project.
  2. I didn’t manage to render anything to the screen whilst completing the project.
  3. And there is an error in the console:

Uncaught ReferenceError: createSlice is not defined.

It could be that I didn’t import the createSlice from redux correctly but I think the syntax is right. Thanks for any help!

And does it say where it is not defined? I can just see the comments stuff and that looks fine regarding the definition of createSlice. What about aticlePreviewSlice and currentArticleSlice? Is createSlice imported there?

createSlice is imported in both the articlePreviewSlice and the currentArticleSlice pages.

The full error message is as follows:

index.compiled.js:7009 Uncaught ReferenceError: createSlice is not defined
at Object.14.@reduxjs/toolkit (index.compiled.js:7009)
at o (index.compiled.js:1)
at index.compiled.js:1
at Object.13…/…/components/CommentForm (index.compiled.js:6914)
at o (index.compiled.js:1)
at index.compiled.js:1
at Object.4…/features/articlePreviews/ArticlePreviews (index.compiled.js:6541)
at o (index.compiled.js:1)
at index.compiled.js:1
at Object.17…/app/App (index.compiled.js:7191)

Not sure if that helps but I can’t see where createSlice is not defined from this error message?

Thanks again!

I replaced my code with the code you provided here and the app still runs fine. So the problem doesn’t seem to be in the code you provided here.
The error message mentions CommentForm.js and ArticlePreviews.js. Both don’t create slices. Maybe the store isn’t configured correctly and the slices aren’t working in the components that import them.
I had big difficulties with the project because nothing I did seemed to have an effect. I ended up adding JSX in any place possible and realised that hitting ‘save’ did not compile the app. The next day it was all there with all the weird stuff I added. Just to consider. Maybe you have a similar problem…

Hey, thank you very much for your time and for double checking my current work. It’s good to know that my code works within yours so I think I might just reset the exercise and redo it and hopefully I’ll spot the error in the code. Thanks again, it’s been very helpful.

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.