Gatsby createNode仅生成单个节点,预期约30个节点问题排查
Gatsby Node API 仅生成单个节点问题
我使用Gatsby Node API结合fetch从远程API拉取数据,遍历数据后预期生成约30个节点,但执行gatsby develop后通过GraphQL查询仅得到1个节点。
代码示例
exports.sourceNodes = async ({ actions, createNodeId, createContentDigest }, configOptions) => { const NODE_TYPE = 'Job'; const response = await fetch( configOptions.url, { headers: { jobs_key: configOptions.access_key }, }, ); const raw_data = await response.json(); const jobs_raw = JSON.parse(JSON.stringify(raw_data)); const jobs = jobs_raw.response.results; console.log(jobs); jobs.forEach(job => { actions.createNode({ ...job, id: createNodeId(`${NODE_TYPE}-${job.id}`), parent: null, children: [], internal: { type: NODE_TYPE, content: JSON.stringify(job), contentDigest: createContentDigest(job) } }) }); };
GraphQL查询输出
{ "data": { "allJob": { "edges": [ { "node": { "id": "a6f3a0ee-d213-54bd-a78c-bc86815667b5" } } ] } }, "extensions": {} }
尝试过的写法(结果相同)
await Promise.all( jobs.map(async (job) => createNode(await processJob(job))) );
示例JSON数据
[ { "Modified Date": "2022-11-03T08:30:56.910Z", "Created Date": "2022-11-03T08:30:56.850Z", "Created By": "1667463646950x933984614718435600", "complete": false, "location": "San Francisco, CA, USA", "roleTitle": "Post Planner", "company": "1667464234467x541822089287434240", "listEmploymentType": [ "Seasonal" ], "eventYesNo": false, "jobStatus": "Draft", "_id": "1667464256451x402163967653838850" }, { "Modified Date": "2022-11-06T00:53:17.123Z", "Created Date": "2022-11-06T00:53:17.076Z", "Created By": "1667695686617x823696282359582100", "complete": false, "location": "Emeryville, CA, USA", "roleTitle": "Some Job", "company": "1667695985945x156747773832069120", "listEmploymentType": [ "Seasonal", "Full-Time", "Part-Time", "Contract", "Event" ], "eventYesNo": false, "jobStatus": "Draft", "geoLocation": { "address": "Emeryville, CA, USA", "lat": 37.8395028, "lng": -122.2892278 }, "_id": "1667695995983x831215741492265000" } ]
问题排查与修复
核心原因
从示例数据可以看到,每个job对象的唯一标识字段是_id,但你创建节点时使用的是job.id——数据中根本不存在id字段,导致所有节点生成的id都是基于undefined,Gatsby会认为这些节点是同一个实体,最终只保留最后一个。
修复代码
将节点id生成逻辑中的job.id替换为job._id,同时可以移除冗余的JSON.parse(JSON.stringify(raw_data))操作:
exports.sourceNodes = async ({ actions, createNodeId, createContentDigest }, configOptions) => { const NODE_TYPE = 'Job'; const response = await fetch( configOptions.url, { headers: { jobs_key: configOptions.access_key }, }, ); const raw_data = await response.json(); const jobs = raw_data.response.results; console.log(jobs); jobs.forEach(job => { actions.createNode({ ...job, // 替换为正确的唯一标识字段 id: createNodeId(`${NODE_TYPE}-${job._id}`), parent: null, children: [], internal: { type: NODE_TYPE, content: JSON.stringify(job), contentDigest: createContentDigest(job) } }) }); };
另外,你尝试的Promise.all写法中,要确保调用的是解构后的actions.createNode,而非未定义的createNode,不过核心问题还是id重复,修复id生成逻辑后即可生成全部节点。
内容的提问来源于stack exchange,提问作者Phillip Smith
相关产品推荐
相关产品推荐

