反应/盖茨比;无法读取null的属性“ map”

时间:2019-11-21 00:05:06

标签: javascript reactjs gatsby

我在最前面有数组数据:

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

我可以在我的帖子模板中随意映射,说我想获取每个工具的名称:

{post.frontmatter.tools.map(item => (
  <span key={item.name}>{item.name}</span>
))}

我将此数组传递给我的SEO组件,如下所示:

<SEO tools={post.frontmatter.tools} />

然后在我的SEO组件中,我可以访问其中的所有内容,这就是我在组件中所拥有的胆量,但是 map函数在这里不起作用,我不确定为什么吗?

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

我想要实现的是从前端获取我的数组数据,并向数组中的每个对象添加架构类型属性,这样最终结果将是:

[
    {
      "@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"
    }
  ]

更新:

我可以通过以下方法将有效的JSON + ld打印到我的头上,但是我的浏览器中仍然有令人讨厌的无法读取属性'map'

  let schemaHowToTools = []

  seo.howToTools.map(tool =>
    schemaHowToTools.push({
      "@type": "HowToTool",
      name: tool.name,
      text: tool.text,
    })
  )

更新#2(有效的解决方案)

感谢@gazdagergo的建议,这是适合我的情况的解决方案。可选链接看起来更好,但此时需要extra plugin

  const schemaTools =
    seo.howToTools &&
    seo.howToTools.map &&
    seo.howToTools.map(tool => {
      const schemaTypeTool = {
        "@type": "HowToTool",
      }
      return Object.assign(schemaTypeTool, tool)
    })

3 个答案:

答案 0 :(得分:0)

也许我们应该运行检查以查看数组是否实际存在。像这样的东西。

if(seo.howToTools.length > 0) {       
      let schemaTools = seo.howToTools
      var schemaToolsWithType = schemaTools.map(function(item) {
        item.@type = "HowToTool"
        return item
      })
}else{
    return ( <div>Loading</div>)

答案 1 :(得分:0)

您需要了解javascript是一种动态语言。在组件中的工具声明的初始点。它只是一个值为undefined的变量。我猜想您的tools数组来自数据库中某个异步活动的地方。 我通常会这样处理这个问题:

  1. 利用ES6的强大功能并在其解构时为工具分配默认值,因此您可能会遇到类似tools=[]的情况 在工具调用的真实价值通过任何调用SEO的工具传递给它之后,此值始终会更改。

  2. 通过工具的价值进行映射。您首先进行长度检查,以查看工具是否为空或具有值。 如果为空....有返回值(例如当前没有工具的值) 如果不是,则可以返回映射的结果。

如果您使用的是状态管理工具(例如redux),则可能会更容易,因为您可以确定该工具目前是否为空,因为您已经从数据库获得了响应。在这种情况下,您可以返回Loading。这也可以通过react,创建依赖于服务器响应的状态[loading,setLoading]来实现。让ne知道是否需要进一步的解释。

答案 2 :(得分:0)

我建议使用安全的导航以避免此类错误。例如:

action(todo) { if (todo.num === 195) console.log("J'ai choisi 195"); }

仅当工具实际上是数组时,这才映射到工具上。

甚至更好,您现在可以使用optional chaining in JS:

const result = tools && tools.map && tools.map(item => { return // etc })