Почему этот функциональный компонент React не может отображать массив (через .map), хранящийся в состоянии? - PullRequest
0 голосов
/ 17 июня 2020

У меня чертовски много времени, чтобы этот компонент правильно взял массив и наметил компоненты на его основе. Хотя я могу видеть этот журнал массива на консоли, по какой-то причине мой компонент (в среде разработки) просто отображается пустым. Итак, я знаю, что тернарный оператор будет истинным, но React тогда не отображает (и, следовательно, не создает JSX) на основе массива.

Примечание: я проверил другие вопросы здесь, на SO, и я не видел ни одной такой. Если я ошибаюсь, укажите мне, пожалуйста, в этом направлении!

Ожидаемое поведение

Я успешно устанавливаю списки в массив с 11 объектами в нем, поэтому DOM должна отображать 11 карточек с использованием этого data.

Наблюдаемое поведение

DOM сначала будет отображать <Skeleton /> s, указывая на то, что тернарный оператор передается блоку ложного кода, а затем DOM просто ничего не отобразит. Пробел.

Пример кода

Обзор (родительский)

    export default function Browse({ user }) {

      // prevents useEffect from infinite looping
      let [loaded, setLoaded] = useState(false)
      let [listings, setListings] = useState(false) // Raw listings array pulled from DB
      let [radius, setRadius] = useState(10000)

      useEffect(() => {
        // Waits for user to come in from Auth Context
        if (typeof user.userDoc !== 'undefined' || listings.length < 1) {
          if (loaded === false) {
            let grabListings = async () => await getLocalListings().then(result => setListings(result))
            grabListings()
          }

          if (listings.length > 1) {
            setLoaded(true)
          }
        }
      }, [user, listings])

      console.log(listings) // successfully shows array in listings state

      return (
        <>
          <Navbar />
          { 
            listings
            ? listings.map(listing => {
                return (
                  <BrowseItem
                    ... // props successfully passed here
                  />
                )
              })
            : <>
                <Container style={{ marginTop: '18px' }}>
                  <Skeleton animation="wave" />
                  <Skeleton animation="wave" />
                  <Skeleton animation="wave" />
                  <Skeleton animation="wave" />
                  <Skeleton animation="wave" />
                </Container>
              </>
          }
          <Footer />
        </>
      )
    }

BrowseItem (дочерний)

    export default function BrowseItem({
      creatorProfilePic,
      creatorUsername,
      docId,
      mainImgUrl,
      productStory,
      productTitle,
      seoTitle,
      user
    }) {

      ...

      let [favorited, setFavorited] = useState(null) // whether user has favorited this item
      let [loaded, setLoaded] = useState(false)

      /** Handles click of the favorite button.
      * Routes to FirebaseCalls function based on state of favorited
      */
      const handleFavorite = async (e) => {
        e.preventDefault()
        let result
        if (favorited) {
          result = await removeFavorite(docId, user.currentUid)
          if (result === 'success') {
            setFavorited(!favorited)
            setSnackMessage('Removed from Favorites')
            setOpen(true)
          } else {
            setSnackMessage('⚠️ There was an error removing this from Favorites')
            setOpen(true)
          }
        } else {
          result = await addFavorite(docId, user.currentUid)
          if (result === 'success') {
              setFavorited(!favorited)
              setSnackMessage('✓ Added to Favorites')
              setOpen(true)
            } else {
              setSnackMessage('⚠️ There was an error adding this to Favorites')
              setOpen(true)
            }
        }
      }

      useEffect(() => {
        if (!loaded) {
          // Determines whether item should default to favorited
          try {
            let userFavorites = user.userDoc.favorites
            if (userFavorites) {
              if (userFavorites.some(id => id === docId)) {
                setFavorited(true)
              }
            }
            setLoaded(true)
          } catch (error) {
            console.log(error)
          }
        }
      }, [user])

      ////////////////////////////////////////////////////////////////////////
      ///////////////////////////// SNACKS ///////////////////////////////////
      ////////////////////////////////////////////////////////////////////////
      let [snackMessage, setSnackMessage] = useState('')
      let [open, setOpen] = useState(null)
      const handleSnackClose = (event, reason) => {
        if (reason === 'clickaway') {
          return
        }
        setOpen(false)
      }

      return (
        <>
          {
            loaded
            ? <>
                <Card>
                  <CardHeader
                    avatar={
                      <Avatar alt={`${creatorUsername} Profile Picture`} src={creatorProfilePic} />
                    }
                    action={
                      <IconButton>
                        <MoreHoriz />
                      </IconButton>
                    }
                    title={productTitle}
                    subheader={`${creatorUsername}`}
                  />
                  <CardMedia
                    className={classes.media}
                    image={mainImgUrl}
                    title={productTitle}
                    onClick={handleImgTouch}
                  />
                  <CardContent>
                    <Typography variant="body2" color="textSecondary" component="p">
                      {productStory}
                    </Typography>
                  </CardContent>
                  <CardActions disableSpacing>
                    <IconButton onClick={handleFavorite}>
                      {
                        favorited
                        ? <Favorite color='primary' />
                        : <Favorite />
                      }
                    </IconButton>
                    <IconButton>
                      <Share />
                    </IconButton>
                  </CardActions>
                </Card>
                <Box mb={4}></Box>
              </>
            : <>
                <Skeleton animation="wave" />
                <Skeleton animation="wave" />
                <Skeleton animation="wave" />
                <Skeleton animation="wave" />
              </>
          }
          <Snackbar
            anchorOrigin={{
              vertical: 'bottom',
              horizontal: 'left',
            }}
            open={open}
            autoHideDuration={3000}
            onClose={handleSnackClose}
            message={snackMessage}
            action={
              <>
                <Button onClick={handleFavorite} color='primary'>UNDO</Button>
                <IconButton size="small" color="inherit" onClick={handleSnackClose}>
                  <Close fontSize="small" />
                </IconButton>
              </>
            }
          />
        </>
      )
    }

Стек

  • "next": "^ 9.4.4"
  • "react": "^ 16.8.6"
  • Тестирование в следующем. js Среда разработки
...