简体   繁体   English

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

[英]Passing a prop to a child from parent with React and Gatsby

Gatsby newbie in here, so be patient with me. 盖茨比新手在这里,请耐心等待我。 I'm building a very basic blog app with Gatsby and React. 我正在用Gatsby和React构建一个非常基本的博客应用程序。 I have a landing page with a section where I display the latest 3 blog posts that were published. 我有一个登录页面,其中包含一个部分,其中显示了最新发布的3篇博客文章。 Until now, everything worked fine with the following code in my index.js file: 到目前为止,我的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
          }
        }
      }
    }
  }
`

However, I would like to separate the latest blog posts section into a separate component (ex. LatestBlogPosts.js ) and import it in my index.js file. 但是,我想将最新的博客文章部分分成一个单独的组件(例如, LatestBlogPosts.js )并将其导入到我的index.js文件中。 Therefore, I copied the markup in a separate file, imported that file in my index.js and all of a sudden there is an error saying: 因此,我将标记复制到一个单独的文件中,然后将该文件导入到index.js ,突然出现一个错误:

TypeError: Cannot read property 'slice' of undefined

I checked and logging posts from the newly created file also returns undefined . 我检查和记录posts来自新创建的文件也将返回undefined The LatestBlogPosts.js file looks like this: LatestBlogPosts.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

And the modified index.js looks like this: 修改后的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
          }
        }
      }
    }
  }
`

I can't seem to understand why posts returns undefined in the LatestBlogPosts.js file? 我似乎无法理解为什么postsLatestBlogPosts.js文件中返回undefined

The problem lies in this expression: 问题在于此表达式:

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

In your first example, this points to BlogIndex ; 在您的第一个示例中, this指向BlogIndex in your second example, you've moved the expression to the render() method of LatestBlogPosts , so the expression will look for the data on that component. 在第二个示例中,您已将表达式移动到LatestBlogPostsrender()方法,因此表达式将在该组件上查找数据。

You need to pass the posts to the child component as a prop: 您需要将这些帖子作为道具传递给子组件:

<LatestBlogPosts posts={posts} />

And reference it in the child's render method: 并在孩子的render方法中引用它:

{this.props.posts.slice(...

You're not passing posts to LatestBlogPosts . 您没有将posts传递到LatestBlogPosts Try: 尝试:

<LatestBlogPosts posts={posts} />

then in LatestBlogPosts you can access with this.props.posts . 然后在LatestBlogPosts您可以使用this.props.posts访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM