I am trying to fetch external data and pass it to the page, but no matter what I try to do I always receive this error. Please help me with some advice, thanks.
instagram.js:
const axios = require('axios')
const queryString = require('query-string')
exports.getData = url => {
const params = queryString.stringify({
url,
maxwidth: 700,
hidecaption: true,
omitscript: true
})
return axios.get(`https://api.instagram.com/oembed/?${params}`)
.then(res => {
const {data} = res
return {
imageUrl: data.thumbnail_url || false,
imageWidth: data.thumbnail_width || false,
imageHeight: data.thumbnail_height || false,
description: data.title || ''
}
})
.catch(err => {
console.log(err)
return false
})
}
gatsby-node.js:
const path = require(`path`)
const config = require('./src/utils/siteConfig')
const instagram = require('./src/utils/instagram')
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const loadProjects = new Promise((resolve, reject) => {
graphql(`
{
allContentfulProject(limit: 10000) {
edges {
node {
slug
sourceUrl
}
}
}
}
`).then(result => {
const posts = result.data.allContentfulProject.edges
const postsPerFirstPage = config.postsPerHomePage
const postsPerPage = config.postsPerPage
const numPages =
Math.ceil(posts.slice(postsPerFirstPage).length / postsPerPage) + 1
// Create each individual project
posts.forEach(async (edge, i) => {
const prev = i === 0 ? null : posts[i - 1].node
const next = i === posts.length - 1 ? null : posts[i + 1].node
const postData = await instagram
.getData(edge.node.sourceUrl)
.catch(err => {
console.log(err)
console.log(`=PROJECTS= : Can't fetch ${edge.node.sourceUrl}`)
})
// console.log(postData)
if (postData) {
createPage({
path: `/projects/${edge.node.slug}/`,
component: path.resolve(`./src/templates/project.jsx`),
context: {
slug: edge.node.slug,
postData,
prev,
next
}
})
}
})
resolve()
})
})
await Promise.all([loadProjects])
}
exports.onCreateWebpackConfig = ({ getConfig, actions }) => {
if (getConfig().mode === 'production') {
actions.setWebpackConfig({
devtool: false
})
}
}
The issue you're having are because you're not awaiting posts.forEach(async (edge, i) => {
This should do the trick
gatsby-node.js:
const path = require(`path`)
const config = require('./src/utils/siteConfig')
const instagram = require('./src/utils/instagram')
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const loadProjects = new Promise((resolve, reject) => {
graphql(`
{
allContentfulProject(limit: 10000) {
edges {
node {
slug
sourceUrl
}
}
}
}
`).then(result => {
const posts = result.data.allContentfulProject.edges
const postsPerFirstPage = config.postsPerHomePage
const postsPerPage = config.postsPerPage
const numPages =
Math.ceil(posts.slice(postsPerFirstPage).length / postsPerPage) + 1
// Create each individual project
Promise.all(posts.map(async (edge, i) => {
const prev = i === 0 ? null : posts[i - 1].node
const next = i === posts.length - 1 ? null : posts[i + 1].node
const postData = await instagram
.getData(edge.node.sourceUrl)
.catch(err => {
console.log(err)
console.log(`=PROJECTS= : Can't fetch ${edge.node.sourceUrl}`)
})
// console.log(postData)
if (postData) {
createPage({
path: `/projects/${edge.node.slug}/`,
component: path.resolve(`./src/templates/project.jsx`),
context: {
slug: edge.node.slug,
postData,
prev,
next
}
})
}
})).then(resolve)
})
})
await Promise.all([loadProjects])
}
If you want a more async-await style you can use this
gatsby-node.js:
const path = require(`path`)
const config = require('./src/utils/siteConfig')
const instagram = require('./src/utils/instagram')
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const results = graphql(`
{
allContentfulProject(limit: 10000) {
edges {
node {
slug
sourceUrl
}
}
}
}
`)
const posts = result.data.allContentfulProject.edges
const postsPerFirstPage = config.postsPerHomePage
const postsPerPage = config.postsPerPage
const numPages =
Math.ceil(posts.slice(postsPerFirstPage).length / postsPerPage) + 1
// Create each individual project
const promises = posts.map(async (edge, i) => {
const prev = i === 0 ? null : posts[i - 1].node
const next = i === posts.length - 1 ? null : posts[i + 1].node
let postData;
try {
postData = await instagram.getData(edge.node.sourceUrl)
} catch(err) {
console.log(err)
console.log(`=PROJECTS= : Can't fetch ${edge.node.sourceUrl}`)
}
// console.log(postData)
if (postData) {
createPage({
path: `/projects/${edge.node.slug}/`,
component: path.resolve(`./src/templates/project.jsx`),
context: {
slug: edge.node.slug,
postData,
prev,
next
}
})
}
}
await Promise.all(promises)
}
We're marking this issue as answered and closing it for now but please feel free to reopen this and comment if you would like to continue this discussion. We hope we managed to help and thank you for using Gatsby! 馃挏
@wardpeet Just a small addition....
For your async example to work you also can't forget to await on the results.
const results = await graphql(`
{
allContentfulProject(limit: 10000) {
edges {
node {
slug
sourceUrl
}
}
}
}
`)
Most helpful comment
The issue you're having are because you're not awaiting
posts.forEach(async (edge, i) => {This should do the trick
gatsby-node.js:If you want a more async-await style you can use this
gatsby-node.js:We're marking this issue as answered and closing it for now but please feel free to reopen this and comment if you would like to continue this discussion. We hope we managed to help and thank you for using Gatsby! 馃挏