Unhandled Runtime Error TypeError: posts.map is not a function

Viewed 44

I am learning nextjs and decides to follow the [build reddit clone tutorial] I found on Youtube, however I kept on running into

posts.map is not a function

please help me out. Thanks in advance. (I'm a complete noob in frontend so please teach me like I'm a kid & please let me know what other things I should put here)

the video: https://youtu.be/W8IK3MeJ5H0?t=6319

Problem

import Post from '../common/Post'
import Vote from './Vote'

const Feed = ({posts}) => {
    return (
        <div className={style.wrapper} >
            {posts.map((post, id) => ( //<----this is the prob
                 <Post {...post} key={id} />
            ))}
        </div>
    )
}

And this is Post.js:

import Vote from '../feed/Vote'
import Actions from '../feed/Actions'
import Info from '../feed/Info'

const style = {
  post: 'flex flex-col space-y-1 cursor-pointer',
  wrapper: 'flex space-x-3 rounded bg-[#1a1a1b]/80 p-2 border border-[#343536]',
  postTitle: 'text-lg font-medium text-[#D7DADC]',
  postContent: 'text-sm font-light text-[#D7DADC]/80 '
}

const Post = ({id, title, author, content, upvotes, downvotes}) => {

  console.log({upvotes})

  return (
    <div className={style.wrapper}>
      <Vote upvotes={upvotes} downvotes={downvotes} />
      <div className={style.post}>
        <Info author={author}/>
        <h1 className={style.postTitle}>{title} </h1>
        <p className={style.postContent}>{content}</p>
        <Actions/>
      </div>

    </div>
  )
}

export default Post

Error

Error message:

Unhandled Runtime Error
TypeError: posts.map is not a function

Error Message Image: https://i.stack.imgur.com/HvINN.png

Attempt Fix 1:

I tried using Object.keys, even though the page could load there will be no data presented. The data should be send from supabase.

const Feed = ({posts}) => {
    return (
        <div className={style.wrapper} >
            {Object.keys(posts).map((post, id) => (
                 <Post {...post} key={id} />
            ))}
        </div>
    )
}

Error Image: https://i.stack.imgur.com/1NlJd.png

Possible Fix but not sure:

I saw some posts from stackoverflow saying the first step is to initialise posts as an array and should be set as

const [posts, setPosts] = useState([]);

I don't really know where to place it and if that works the same if the data is exported externally. (and if the data is in a array)

The post: (Cannot fix "Uncaught TypeError: posts.map is not a function" error)

This is my data in supabase: https://i.stack.imgur.com/BdOaG.png

This is what I'm expecting to render: https://i.stack.imgur.com/TuCRQ.png

(I know following tutorials is bad but I use it to learn a few tricks and the correct usage of it, I'm already 4 hours in so I'm trying to resolve this error)

Edit

Index.tsx: this is where Feed is used

const Home: NextPage = () => {

  const {currentUser,fetcher} = useContext(RedditContext)

  const [myPosts, setMyPosts] = useState([])


  const {data,error} = useSWR('/api/get-posts',fetcher, {refreshInterval: 200})


  //update or inset new 
  const saveAndUpdateUser = async() =>{
    if (!currentUser) return
    
    await supabase.from ('users').upsert({ //add to database update that user
      email: currentUser.user_metadata.email,
      name: currentUser.user_metadata.full_name,
      profileImage: currentUser.user_metadata.avatar_url,
    }) 
  }

  useEffect(()=>{
    if (!data) return

    setMyPosts(data.data)
  },[data])

  useEffect(()=>{
    saveAndUpdateUser()
    console.log('save user')
  },[currentUser])

  return (
  <>
    {currentUser? <HomePage myPosts={myPosts}/> : <Login/>} 
    {/* if login cool lets see post if not go login */}
    </>
    )
  }

const HomePage = (myPosts) => { 
return(
  <div className={style.wrapper}>
  <Header />
  <Banner />
  <main className={style.main}>
    <div className={style.content}>
      <CreatePost />
      <Feed posts={myPosts} /> //<--this is where Feed is used
    </div>
    <div className={style.infoContainer}>
      <About />
    </div>
  </main>
  </div>

)

}
export default Home

1 Answers

The issue is due to const HomePage = (myPosts). Component functions accept the object usually called props, which contains data passed as an attributes. So in your case myPosts is the object that looks like {myPosts: [...]} instead of what you are expecting, the plain array.

To fix an issue you need either to rename myPosts to props (naming convention) and call <Feed posts={props.myPosts} /> (<Feed posts={myPosts.myPosts} /> without renaming), either to use destructuring and use const HomePage = ({myPosts}).

Related