I have array data in frontmatter:
tools:
- name: Hammer
text: Use a wooden hammer
- name: Glue
text: PVA glue works best for this application
- name: Paint
text: Choose your favourite colour
Which I can map over in my post template no trouble, say I want to get the name of each tool:
{post.frontmatter.tools.map(item => (
<span key={item.name}>{item.name}</span>
))}
I am passing this array to my SEO component like this:
<SEO tools={post.frontmatter.tools} />
And then in my SEO component I have access to all of it there, here's the guts of what I have in my component but the map function doesn't work here and I'm not sure why?
import React from "react"
import Helmet from "react-helmet"
const SEO = ({
type,
tools,
}) => {
const seo = {
type: type,
howToTools: tools,
}
let schemaTools = seo.howToTools
var schemaToolsWithType = schemaTools.map(function(item) {
item.@type = "HowToTool"
return item
})
console.log(newArray)
const schemaType = seo.type
let schemaHowTo = null
if (schemaType === "howto") {
schemaHowTo = {
/* HowTo Schema */
"@context": "http://schema.org",
"@type": "HowTo",
tool: schemaToolsWithType,
}
}
let schemaArticle = null
if (schemaType === "article") {
schemaArticle = {
{/* Article schema here */}
}
}
return (
<>
<Helmet>
{/* Insert schema.org data conditionally (HowTo/Article)*/}
{schemaType === "howto" && (
<script type="application/ld+json">
{JSON.stringify(schemaHowTo)}
</script>
)}
{schemaType === "article" && (
<script type="application/ld+json">
{JSON.stringify(schemaArticle)}
</script>
)}
</Helmet>
</>
)
}
export default SEO
What I am wanting to achieve is get my array data from front matter, and to each object in the array add the schema type property so the final outcome would be:
[
{
"@type": "HowToTool",
"name": "Hammer",
"text: "Use a wooden hammer"
},
{
"@type": "HowToTool",
"name": "Glue",
"text: "PVA glue works best for this application"
},
{
"@type": "HowToTool",
"name": "Hammer",
"text: "Choose your favourite colour"
}
]
Update:
I'm able to print valid JSON+ld to my head with the following approach but I still have the pesky cannot read property 'map' of null in my browser.
let schemaHowToTools = []
seo.howToTools.map(tool =>
schemaHowToTools.push({
"@type": "HowToTool",
name: tool.name,
text: tool.text,
})
)
Update #2 (Working solution)
Thanks to suggestions from @gazdagergo this was the solution that worked for my situation. The optional chaining looks better yet but at this point requires an extra plugin.
const schemaTools =
seo.howToTools &&
seo.howToTools.map &&
seo.howToTools.map(tool => {
const schemaTypeTool = {
"@type": "HowToTool",
}
return Object.assign(schemaTypeTool, tool)
})