#javascript #reactjs #asynchronous #load #mobx
#javascript #reactjs #асинхронный #загрузить #mobx
Вопрос:
Извините, потому что это будет длинный пост, но я был бы очень признателен за помощь. Я пытался заставить его работать, но безуспешно.
Я делаю вызов в базу данных для захвата изображений, во время этого вызова я хочу, чтобы загрузчик был активным. Загрузчик не отображается во время вызова (когда я его жестко кодирую, он работает). Другая проблема заключается в <NoResults />
компоненте. Предполагается, что он отображается, когда запрос к базе данных возвращается пустым. Однако этот компонент выполняет рендеринг во время выполнения вызова api.
TLDR Мне нужен загрузчик во время вызова api, но вместо этого <NoResults />
компонент выполняет рендеринг, а затем рендеринг данных, возвращенных из БД.
С использованием mongodb, express, mobx и react.
Медиа-хранилище Mobx:
export class MediaStore {
@observable loading = true
@observable trending = []
@action setLoading = (bool) => { this.loading = bool }
@action getTrending = async (category, pageNum, input) => {
this.setLoading(true)
this.error = false
let cancel
axios({
method: 'GET',
url: `http://localhost:3001/media/trending?category=${category}amp;page=${pageNum}amp;input=${input}`,
cancelToken: new axios.CancelToken(c => cancel = c)
}).then(res => {
this.trending =
[...new Set([...this.trending, ...res.data.creators]
.map(JSON.stringify))].map(JSON.parse)
this.setHasMore(res.data.creators.length > 0)
this.setLoading(false)
}).catch(e => {
if (axios.isCancel(e)) return
this.error = true
})
return () => cancel
}
}
Компонент MediaCards:
const MediaCards = inject('userStore', 'mediaStore')(observer((props) => {
const ref = useCreators(props.mediaStore);
const location = useLocation()
const classes = useStyles()
const { isLoggedIn, favorites } = props.userStore;
const { trending, loading } = props.mediaStore;
const { media, header, mediaCard } =
location.pathname === '/dashboard' amp;amp; (!isLoggedIn || !favorites.length)
? { media: [], header: 'basic', mediaCard: false }
: location.pathname === '/dashboard'
? { media: favorites, header: 'basic', mediaCard: true }
: { media: trending, header: 'explore', mediaCard: true }
const renderMediaCards = (media) => {
return media.map((data, i) => {
let isFavorite = favorites.some(f => data._id === f._id)
if (header === 'explore' amp;amp; media.length === i 1) {
return <MediaCard lastRef={ref} id={data._id} img={data.img} isFavorite={isFavorite} twitchName={data.twitch} key={data._id} />
}
return <MediaCard id={data._id} img={data.img} isFavorite={isFavorite} twitchName={data.twitch} key={Math.random()} />
})
}
return (
<>
<Header page={header} />
{header === 'explore' ? <CategoryBar /> : <Paper className={classes.paperTopMedia}></Paper>}
{mediaCard
? <Paper className={classes.paperMedia}>
<Grid container>
<GridList cellHeight={180} className={classes.rootMedia}>
{!trending.length amp;amp; !loading amp;amp; <NoResults />}
{!loading amp;amp; renderMediaCards(media)}
{loading amp;amp; <Loading />}
</GridList>
</Grid>
</Paper>
: <EmptyCard />
}
</>
)
}))
Комментарии:
1. На первый взгляд ваш код выглядит нормально. У вас есть какое-то предупреждение или ошибки в консоли? Используете ли вы последнюю версию react и mobx? Включено ли у вас пакетирование? github.com/mobxjs/mobx-react-lite#observer-batching
2. Да, я все это сделал. Никаких предупреждений или ошибок. ‘Trending’ начинается как пустой массив, поэтому сначала он отображает <NoResults/>, пока не вернется из БД с полным списком ‘trending’. Я хочу, чтобы у него был загрузчик, пока он не вернется из БД с результатами или не вернется пустым.
3. Ну, тогда это действительно странно. Может быть, это что-то с
useCreators
перехватом, вы передаете MediaStore туда, может быть, это как-то изменяет его? Не могу думать ни о чем другом без воспроизведения в песочнице.