Search code examples
reactjstypescriptreduxreact-redux

Cannot read properties of undefined using redux ERROR


I am having an error when refreshing my browser.

Uncaught TypeError: Cannot read properties of undefined (reading 'title')

And it keeps on repeating for all of my states (title, content, id) until I delete them from code down below... And also it works fine until I refresh the page.

import React, { FC, useEffect } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import AddComment from 'src/components/ui/AddComment/AddComment';
import CommentSection from 'src/components/ui/CommentSection/CommentSection';
import PostContent from 'src/components/ui/PostContent/PostContent';
import PostHeader from 'src/components/ui/PostHeader/PostHeader';
import {useAppSelector } from 'src/store/app/hooks';

const Post: FC = () => {
  const { id } = useParams();
  const { posts } = useAppSelector((state) => state.post);

  return (
    <div>
      <PostHeader
        header={<h2>{posts.find(p => p.id === parseInt(id)).title}</h2>}
      >
        <div>
          {posts.find(p => p.id === parseInt(id)).content}
        </div>
      </PostHeader>
      <PostContent
        content={<div>{posts.find(p => p.id === parseInt(id)).content}</div>}
      />
      <AddComment id={id} />
      <CommentSection id={id} />
    </div>
  )
};

export default Post;

I also want to stop posts from dissapearing after refresh.


Solution

  • Issue

    The basic issue is that Array.prototype.find returns undefined when there is no match. The code should account for this and handle not having a matching post object gracefully.

    Solution

    I suggest only searching the posts array once and saving the result. If the result is truthy then access the properties, otherwise render null or some other fallback UI.

    Example:

    const Post : FC = () => {
      const { id } = useParams();
      const { posts } = useAppSelector((state) => state.post);
    
      const post = posts.find(p => String(p.id) === id);
    
      if (!post) {
        return <div>No post here.</div>;
      }
    
      return (
        <div>
          <PostHeader header={<h2>{post.title}</h2>}>
            <div>{post.content}</div>
          </PostHeader>
          <PostContent content={<div>{post.content}</div>} />
          <AddComment id={id} />
          <CommentSection id={id} />
        </div>
      )
    };