Why does my app appear and disappear after a second and logs type error : can’t read property of (filter)

Viewed 16

Also, when a user logs in, I retrieve user’s data from firebase and store in the movie data state for rendering.



 import React, { useState, useContext, useEffect } from 'react'
import { app, database } from '../firebaseConfig'
import { doc, setDoc } from 'firebase/firestore'
import data from 'StarterAssets/data.json'

//Toastify package
import { toast } from 'react-toastify'

//Get Data stored in local storage
const getLocalStorage = () => {
  let movieData = localStorage.getItem('movieData')
  if (movieData) {
    return JSON.parse(localStorage.getItem('movieData'))
  } else {
    return data
  }
}

const AppContext = React.createContext()

const AppProvider = ({ children }) => {
  const [userID, setUserID] = useState('')
  const [movieData, setMovieData] = useState(getLocalStorage())
  //const [movieData, setMovieData] = useState(data)
  const [searchValue, setSearchValue] = useState('')

  useEffect(() => {
    localStorage.setItem('movieData', JSON.stringify(movieData))
  }, [movieData])

  //loops over an array, compares the ids of passed and contained and changes the value of bookmarked prop
  const bookmarkMovie = (id) => {
    const newState = movieData.map((obj) => {
      // if id equals obj[id], update bookmarked property

      if (obj.id === id) {
        const { isBookmarked } = obj
        return { ...obj, isBookmarked: !isBookmarked }
      }

      // else return the object as it is
      return obj
    })

    setMovieData(newState)
  }
  console.log(movieData)
  const searching = {
    home: 'Search for movies or TV series',
    tv: 'TV series',
    movies: 'movies',
    bookmarks: 'bookmarked shows',
  }

  useEffect(() => {
    const sendData = async () => {
      await setDoc(doc(database, 'users', userID), { movieData })
    }

    sendData().catch((error) => toast.error(error))
  }, [movieData])

  return (
    <AppContext.Provider
      value={{
        userID,
        setUserID,
        searching,
        setMovieData,
        movieData,
        bookmarkMovie,
        searchValue,
        setSearchValue,
      }}
    >
      {children}
    </AppContext.Provider>
  )
}

export const useGlobalContext = () => {
  return useContext(AppContext)
}

export { AppContext, AppProvider }

Here’s my Home.jsx file where the error(Type error: Cannot read property of (filter) in home.jsx is picked up from the console. I omitted the import statements due to limits for posts.


import React from 'react'
import styles from 'Pages/Home/home.module.scss'
import { useGlobalContext } from 'Hooks/context'
import Show from 'Components/Show'
import SearchResults from 'Components/SearchResults'

//Abstract Data // Icons
import IconPlay from 'StarterAssets/assets/icon-play.svg'
import iconBookmarkEmpty from 'StarterAssets/assets/icon-bookmark-empty.svg'
import iconBookmarkFull from 'StarterAssets/assets/icon-bookmark-full.svg'

const Home = () => {
  const { movieData, bookmarkMovie, searchValue } = useGlobalContext()

  //Array of recommended movie section
  const recommendedMovies = movieData.filter((movie) => {
    return movie.thumbnail?.regular && !movie.isTrending
  })

  //Display search results
  if (searchValue) return <SearchResults movieArray={movieData} />
  //Return the entire array if the search value is empty... More like the default component
  return (
    <section className={styles.main}>
      <div className={styles.trending}>
        <h1 className='heading-large'>Trending</h1>
        <div className={`${styles.trend__grid} ${styles.snap__inline}`}>
          {movieData
            .filter((movie) => {
              return movie.thumbnail?.trending
            })
            .map(
              ({
                title,
                id,
                thumbnail: { trending },
                year,
                category,
                rating,
                isBookmarked,
              }) => {
                return (
                  <div key={id} className={`${styles.trend} packed`}>
                    <picture className={styles.wrapper__image}>
                      <source
                        media='(min-width: 801px)'
                        srcSet={trending.large}
                      />
                      <img
                        src={trending.small}
                        alt='Top Trending movie'
                        className={styles.trend__img}
                      />
                    </picture>
                    <div className={styles.icon__wrapper}>
                      <img src={IconPlay} alt='click to play movie' />
                      <p>Play</p>
                    </div>

                    <div
                      className={styles.bookmark__wrapper}
                      onClick={() => bookmarkMovie(id)}
                    >
                      <img
                        src={
                          isBookmarked ? iconBookmarkFull : iconBookmarkEmpty
                        }
                        alt='click to bookmark'
                      />
                    </div>
                    <div
                      className={`${styles.category__wrapper} ${styles.category__align}`}
                    >
                      <div className={styles.types}>
                        <p className={styles.year}>{year}</p>
                        <span></span>
                        <p className={styles.type}>{category}</p>
                        <span></span>
                        <p className={styles.rating}>{rating}</p>
                      </div>
                      <h2 className={styles.subheading}>{title}</h2>
                    </div>
                  </div>
                )
              }
            )}
        </div>
      </div>
      <div className={styles.recommended}>
        <h1 className='heading-large'>Recommended For You</h1>
        <div className={styles.recommend__grid}>
          {recommendedMovies.map((movie) => {
            return (
              <Show key={movie.id} {...movie} bookmarkMovie={bookmarkMovie} />
            )
          })}
        </div>
      </div>
    </section>
  )
}

export default Home

My login functionality is situated here in the login.jsx:

onSubmit: async (values, { resetForm }) => {
      //Submitting user's details for verification
      let oldUser
      try {
        oldUser = await signInWithEmailAndPassword(
          auth,
          formik.values.email,
          formik.values.password
        )
        toast.success('Logged In Successfully')
        resetForm()
        navigate('/')
      } catch (error) {
        toast.error('Wrong Details / check your network')
      }
      const { user } = oldUser
      setUserID(user.uid)

      //Getting logged in user's data from firebase
      const docRef = doc(database, 'users', user.uid)
      const docSnap = await getDoc(docRef)
      //Storing said data into state via context API
      const { data } = docSnap.data()
      //setMovieData(docSnap.data())
      setMovieData(data)
    },
  })

Here’s the link to the site: entertainment-mini-app.netlify.app A demo login details email : qwe@gmail.com Password: 123456

I will appreciate all the help I can get in order to feel I’ve fully achieved something today… Cause I’ve been on this bug for longer than I thought. I opted for local storage because I wanted to persist state when the page is refreshed. because I’m altering the property of isbookmarked whenever the bookmarked icon is clicked.

0 Answers
Related