使用React和Gatsby将道具从父母传递给孩子

时间:2019-01-06 13:05:42

标签: javascript reactjs gatsby

盖茨比新手在这里,所以请耐心等待我。我正在用Gatsby和React构建一个非常基本的博客应用程序。我有一个登录页面,其中包含一个部分,其中显示了最新发布的3篇博客文章。到目前为止,在我的index.js文件中使用以下代码,一切正常:

import React from 'react'
import { Link, graphql } from 'gatsby'
import get from 'lodash/get'

import Bio from '../components/Bio'
import Layout from '../components/Layout'
import SEO from '../components/SEO'
import { formatReadingTime } from '../utils/helpers'

class BlogIndex extends React.Component {
  render() {
    const siteTitle = get(this, 'props.data.site.siteMetadata.title')
    const siteDescription = get(
      this,
      'props.data.site.siteMetadata.description'
    )
    const size = 3
    const posts = get(this, 'props.data.allMarkdownRemark.edges')

    return (
        <div className="container">
          <Layout location={this.props.location} title={siteTitle}>
            <SEO />
            <Bio />
            <section>
              <div>
                {posts.slice(0, size).map(({ node }) => {
                  const title = get(node, 'frontmatter.title') || node.fields.slug
                  return (
                    <div key={node.fields.slug}>
                      <h3>
                        <Link to={node.fields.slug}>
                          {title}
                        </Link>
                      </h3>
                      <p>
                        {node.frontmatter.date}
                        {` • ${formatReadingTime(node.timeToRead)}`}
                      </p>
                      <p
                        dangerouslySetInnerHTML={{ __html: node.frontmatter.spoiler }}
                      />
                    </div>
                  )
                })}
              </div>
            </section>
          </Layout>
        </div>
    )
  }
}

export default BlogIndex

export const pageQuery = graphql`
  query {
    site {
      siteMetadata {
        title
        description
      }
    }
    allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
      edges {
        node {
          fields {
            slug
          }
          timeToRead
          frontmatter {
            date(formatString: "MMMM DD, YYYY")
            title
            spoiler
          }
        }
      }
    }
  }
`

但是,我想将最新的博客文章部分分为一个单独的组件(例如LatestBlogPosts.js),并将其导入我的index.js文件中。因此,我将标记复制到一个单独的文件中,然后将该文件导入我的index.js中,突然之间出现一个错误:

TypeError: Cannot read property 'slice' of undefined

我检查并从新创建的文件登录posts也会返回undefinedLatestBlogPosts.js文件如下所示:

import React from 'react'
import { Link } from 'gatsby'
import {formatReadingTime} from "../utils/helpers";
import get from 'lodash/get'

class LatestBlogPosts extends React.Component {
  render() {
    const size = 3
    const posts = get(this, 'props.data.allMarkdownRemark.edges')

    return (
      <section>
        <div>
          {posts.slice(0, size).map(({ node }) => {
            const title = get(node, 'frontmatter.title') || node.fields.slug
            return (
              <div key={node.fields.slug}>
                <h3>
                  <Link to={node.fields.slug}>
                    {title}
                  </Link>
                </h3>
                <p>
                  {node.frontmatter.date}
                  {` • ${formatReadingTime(node.timeToRead)}`}
                </p>
                <p
                  dangerouslySetInnerHTML={{ __html: node.frontmatter.spoiler }}
                />
              </div>
            )
          })}
        </div>
      </section>
    )
  }
}

export default LatestBlogPosts

修改后的index.js如下所示:

import React from 'react'
import { Link, graphql } from 'gatsby'
import get from 'lodash/get'

import Bio from '../components/Bio'
import Layout from '../components/Layout'
import SEO from '../components/SEO'
import Footer from '../components/Footer'
import { formatReadingTime } from '../utils/helpers'
import { rhythm } from '../utils/typography'
import LatestBlogPosts from "../components/LatestBlogPosts";

class BlogIndex extends React.Component {
  render() {
    const siteTitle = get(this, 'props.data.site.siteMetadata.title')
    const siteDescription = get(
      this,
      'props.data.site.siteMetadata.description'
    )

    return (
        <div className="container-fluid">
          <Layout location={this.props.location} title={siteTitle}>
            <SEO />
            <Bio />
            <LatestBlogPosts />
            <Footer />
          </Layout>
        </div>
    )
  }
}

export default BlogIndex

export const pageQuery = graphql`
  query {
    site {
      siteMetadata {
        title
        description
      }
    }
    allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
      edges {
        node {
          fields {
            slug
          }
          timeToRead
          frontmatter {
            date(formatString: "MMMM DD, YYYY")
            title
            spoiler
          }
        }
      }
    }
  }
`

我似乎无法理解为什么postsundefined文件中返回LatestBlogPosts.js

2 个答案:

答案 0 :(得分:2)

问题出在以下表达式中:

posts = get(this, 'props.data.allMarkdownRemark.edges')

在您的第一个示例中,this指向BlogIndex;在第二个示例中,您已将表达式移至render()的{​​{1}}方法中,因此表达式将在该组件上查找数据。

您需要将帖子作为道具传递给子组件:

LatestBlogPosts

并在孩子的render方法中引用它:

<LatestBlogPosts posts={posts} />

答案 1 :(得分:2)

您没有将>>> format(19.2189, '.3f') '19.219' 传递给posts。试试:

LatestBlogPosts

然后在<LatestBlogPosts posts={posts} />中使用LatestBlogPosts进行访问。