Search code examples
reactjsreduxserver

React Redux toolkit


I have PostsSlice which provides data from server about posts enter image description here

PostSlice Code:

const initialState = {
  posts: [],
};

const post = createSlice({
  name: "post",
  initialState,
  reducers: {
    getPosts(state, action) {
      state.posts = action.payload.posts;
    },
  },
});

const { getPosts } = post.actions;

export function GetPostByInterests() {
  return async (dispatch) => {
    try {
      const response = await API.get("/posts", {
        params: {
          limit: 10,
          offset: 0,
        },
      });
      const data = response.data;
      const posts = data.data;

      dispatch(
        getPosts({
          posts: posts,
        })
      );
    } catch (e) {}
  };
}

I'm trying to pull out the user's image in the frontend in the post card and I get an error: Uncaught TypeError: posts.author.avatar is undefined

FrontEnd Code

export const News = () => {
  const dispatch = useDispatch();
  const posts = useSelector((state) => state.post.posts);
 
  useLayoutEffect(() => {
    dispatch(GetPostByInterests());
  }, []);

  return (
    <div className="container-md shadow-lg bg-white py-10 px-8 mx-[5rem] my-[1rem] rounded-md">
      {posts.map((posts) => (
        <PostCard key={posts.id} posts={posts} />
      ))}
    </div>
  );
};

PostCard FrontEnd image display:

        <img
          className="w-12 h-12 rounded-full object-cover mr-4 shadow"
          src={posts.author.avatar.url}
          alt="avatar"
        ></img>

Solution

  • Welcom to Stackoverflow @memphis

    You need to use Optional Chaining in the src of the img tag. Like this:

    <img
      className="w-12 h-12 rounded-full object-cover mr-4 shadow"
      src={posts?.author.avatar.url}
      alt="avatar"
    ></img>
    

    It's also good practice to use a Ternary Operator when mapping through the data that is coming from the API, in order to avoid getting undefined errors when the data is being fetched:

    // If posts aren't loaded yet, show a message
    // (Or you can even show a loading spinner)
    {!posts?.length ? <p>Nothing to Show</p> : posts.map((posts) => (
      <PostCard key={posts.id} posts={posts} />
    ))}