#javascript #reactjs #es6-promise
#javascript #reactjs #es6-обещание
Вопрос:
У меня есть довольно простой компонент, в котором я сначала извлекаю статью
const { slug } = useParams();
const [document, setDocument] = useState({});
useEffect(() => {
setDocument(blogStore.fetchBlog(slug));
}, []);
чтобы затем отобразить его
<GridItem>
{!blogStore.isLoading amp;amp; (
<Box as="article">
<Heading as="h2" fontSize="3xl" mb={2}>
{document.items[0].fields.title}
</Heading>
<AspectRatio ratio={16 / 9} mb={6}>
<Image
src={
document.items[0].fields.mainImage
.fields.file.url
}
// alt={props.mainImageTitle}
/>
</AspectRatio>
<ReactMarkdown
plugins={[gfm]}
children={document.items[0].fields.markdownBody}
/>
</Box>
)}
</GridItem>
Ошибка, которую он выдает, такова
TypeError: Cannot read property '0' of undefined
.
Длинная ошибка выглядит следующим образом
BlogDetail.js:43 Uncaught (in promise) TypeError: Cannot read property '0' of undefined
at BlogDetail (BlogDetail.js:43)
at runAsReaction (es.es5.js:92)
at reaction (es.es5.js:149)
at BlogDetail (view.js:62)
at renderWithHooks (react-dom.development.js:14985)
at updateFunctionComponent (react-dom.development.js:17356)
at updateSimpleMemoComponent (react-dom.development.js:17215)
at updateMemoComponent (react-dom.development.js:17092)
at mountLazyComponent (react-dom.development.js:17714)
at beginWork (react-dom.development.js:19055)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
at invokeGuardedCallback (react-dom.development.js:4056)
at beginWork$1 (react-dom.development.js:23964)
at performUnitOfWork (react-dom.development.js:22776)
at workLoopSync (react-dom.development.js:22707)
at renderRootSync (react-dom.development.js:22670)
at performSyncWorkOnRoot (react-dom.development.js:22293)
at react-dom.development.js:11327
at unstable_runWithPriority (scheduler.development.js:646)
at runWithPriority$1 (react-dom.development.js:11276)
at flushSyncCallbackQueueImpl (react-dom.development.js:11322)
at flushSyncCallbackQueue (react-dom.development.js:11309)
at batchedUpdates$1 (react-dom.development.js:22387)
at batch (batch.js:21)
at Object.apply (batch.js:40)
Мой соответствующий blogStore.js
код выглядит следующим образом
import { store } from '@risingstack/react-easy-state';
import { createClient } from 'contentful';
const client = createClient({
space: '...',
accessToken: ...,
});
const blogStore = store({
client: client,
blogs: [],
isLoading: false,
async fetchBlogs() {
blogStore.isLoading = true;
const response = await blogStore.client.getEntries({
content_type: 'blogPost',
order: 'sys.createdAt',
});
blogStore.blogs = response.items;
blogStore.isLoading = false;
},
async fetchBlog(slug) {
blogStore.isLoading = true;
const response = await blogStore.client.getEntries({
content_type: 'blogPost',
'fields.slug': slug,
});
// console.log(response.items[0].fields.blogBody);
return response;
},
});
Комментарии:
1. Попробуйте выйти из системы, что
document
действительно возвращает. Я предполагаю, что у него нетitems
свойства.2. То, что сказал @AndrewLohr, в сочетании с этим также может привести к превышению нулевого значения начального состояния. Я бы добавил условие перед вашей разметкой просто как 1 для лучших практик, когда, если что-то влияет
!document || !document.item || !document.item.length
, появляется альтернативная разметка, например загрузчик. Если вы используете необязательную цепочку,if(!document?.item?.length) { return <div>loading</div> }
.3. Так
document
же как и массив с одним элементом в нем (contentful сделал это так, чтобы так было удобнее, потому что я могу искать элемент по его слагу, а не искать запись по ееid
, которую сначала нужно извлечь).4. Ага. Таким образом, он переходил в неопределенное состояние. Хотя интересно, что после выполнения обещания оно не загружает автоматически статью вместо загрузочного заполнителя