У меня чертовски много времени, чтобы этот компонент правильно взял массив и наметил компоненты на его основе. Хотя я могу видеть этот журнал массива на консоли, по какой-то причине мой компонент (в среде разработки) просто отображается пустым. Итак, я знаю, что тернарный оператор будет истинным, но 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 Среда разработки