首页 > 解决方案 > 在 Gatsby Netlify 启动器中,使用自定义预览组件、不可变 entry.getIn 和 widgetsFor 从列表中返回空对象

问题描述

我已经设法使用 react-scrollmagic 和 react-gsap 构建了一个带有“幻灯片”的自定义主页。我已更改 index.md 以包含每张幻灯片所需的字段和列表,以及 static/admin/config.yml 中的字段定义,以便 Netlify 将它们拾取。我已经更新了 index-page.js 模板以对我的新字段进行 Proptype 检查,并且所有内容都可以正常加载到 index-page 模板中。

我正在努力解决的是 CMS 的预览组件。无论我尝试了什么,我都会返回幻灯片/列表的空对象。我已经尝试过地图,以及 Immutable 的 getIn 的所有可能配置。我错过了什么?

这是 static/admin/config.yml

backend:
name: git-gateway
branch: master

media_folder: static/img
public_folder: /img

collections:
  - name: "blog"
    label: "Blog"
    folder: "src/pages/blog"
    create: true
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
    fields:
      - {label: "Template Key", name: "templateKey", widget: "hidden", default: "blog-post"}
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Description", name: "description", widget: "text"}
      - {label: "Featured Post", name: "featuredpost", widget: "boolean"}
      - {label: "Featured Image", name: "featuredimage", widget: image}
      - {label: "Body", name: "body", widget: "markdown"}
      - {label: "Tags", name: "tags", widget: "list"}

  - name: "pages"
    label: "Pages"
    files:
      - file: "src/pages/index.md"
        label: "Landing Page"
        name: "index"
        fields:
          - {label: "Template Key", name: "templateKey", widget: "hidden", default: "index-page"}
          - {label: Title, name: title, widget: string}
          - {label: Image, name: image, widget: image}
          - {label: Slides, name: slides, widget: list, fields: [{label: Sidebar Hero, name: sidebarHero, widget: text},{label: Sidebar Description, name: sidebarDescription, widget: text},{label: Slide Blurb, name: slideBlurb, widget: text},{label: Slide Image, name: slideImg, widget: image}]}
      - file: "src/pages/about/index.md"
        label: "About"
        name: "about"
        fields:
          - {label: "Template Key", name: "templateKey", widget: "hidden", default: "about-page"}
          - {label: "Title", name: "title", widget: "string"}
          - {label: "Body", name: "body", widget: "markdown"}

这是 index-page.js 模板

import React from 'react';
import PropTypes from 'prop-types';
import { graphql } from 'gatsby';
import PreviewCompatibleImage from '../components/PreviewCompatibleImage';
import Layout from '../components/Layout';
import { Tween, Timeline } from 'react-gsap';
import { Controller, Scene } from 'react-scrollmagic';
import geoShape from '../../static/img/home/geo_shape.png';

const tweenProps = {
  ease: 'Strong.easeOut',
  to: {
    rotationY: 180,
  }
}

const FlippyGeoShape = ({progress}) => {
  return (
    <Timeline
      totalProgress={progress * 2}
      paused
    >
      <Tween {...tweenProps}>
        <img src={geoShape} />
      </Tween>
    </Timeline>
  );
};

export const IndexPageTemplate = ({
  image,
  title,
  slides,
}) => {
    const slide2 = slides[0].slide;
    const slide3 = slides[1].slide;
    return (
    <div className="home-slides">
      <Controller globalSceneOptions={{ triggerHook: 'onLeave' }}>
        <Scene pin>
          <div className="panel panel-1">
              <PreviewCompatibleImage
                imageInfo={{
                  image: !!image.childImageSharp ? image.childImageSharp.fluid.src : image,
                  alt: `featured image thumbnail for logo`,
                  style: {
                    width: '500px',
                  }
                }}
              />
              <span>
                <span className="scroll-bob">SCROLL</span>
              </span>
          </div>
        </Scene>
        <Scene pin pinSettings={{ pushFollowers: false }} duration="900">
          {(progress) => (
          <div className="panel panel-2">

            <div className="sidebar">
              <p className="purpose">
                {slide2.sidebarHero}
              </p>
            </div>

            <div className="right">
              <div className="slideText">
                <p>
                  {slide2.slideBlurb}
                </p>
              </div>
              <span>
                <span className="scroll-bob">SCROLL</span>
              </span>
            </div>
            <div className="animatedGeoShape">
              <FlippyGeoShape progress={progress} />
            </div> 
          </div>
          )}
        </Scene>
        <Scene pin>
          <div className="panel panel-3">
            <div className="left">
              <div className="slideText">
                <p>
                  {slide3.slideBlurb}
                </p>
                <PreviewCompatibleImage
                  imageInfo={{
                      image: !!slide3.slideImg.childImageSharp ? slide3.slideImg.childImageSharp.fluid.src : slide3.slideImg,
                      alt: `Himitsu Lounge Featured Image`,
                  }}
                />
              </div>
              <span>
                <span className="scroll-bob">SCROLL</span>
              </span>
            </div>
            <div className="sidebar">
                <p className="sidebar-hero">
                  {slide3.sidebarHero}
                </p>
                <p className="sidebar-desc">
                  {slide3.sidebarDescription}
                </p>
            </div>
          </div>
        </Scene>
      </Controller>
    </div>
    )
  }


IndexPageTemplate.propTypes = {
  image: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
  title: PropTypes.string,
  slides: PropTypes.arrayOf(PropTypes.shape({
    slide: PropTypes.shape({
        sidebarHero: PropTypes.string,
        sidebarDescription: PropTypes.string,
        slideBlurb: PropTypes.string,
        slideImg: PropTypes.object,
      })
    })
  )
}


const IndexPage = ({ data }) => {
  const { frontmatter } = data.markdownRemark

  return (
    <Layout location="/">
      <IndexPageTemplate
        image={frontmatter.image}
        title={frontmatter.title}
        slides={frontmatter.slides}
      />
    </Layout>
  )
}

IndexPage.propTypes = {
  data: PropTypes.shape({
    markdownRemark: PropTypes.shape({
      frontmatter: PropTypes.object,
    }),
  }),
}

export default IndexPage

export const pageQuery = graphql`
  query IndexPageTemplate {
    markdownRemark(frontmatter: { templateKey: { eq: "index-page" } }) {
      frontmatter {
        title
        image {
          childImageSharp {
            fluid(maxWidth: 2048, quality: 100) {
              ...GatsbyImageSharpFluid
            }
          }
        }
        slides {
          slide {
            sidebarHero
            slideBlurb
          }
          slide {
            sidebarHero
            sidebarDescription
            slideBlurb
            slideImg {
              childImageSharp {
                fluid(maxWidth: 2048, quality: 100) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
          }
        }
      }
    }  
  }
`

这是此页面的预览组件:

import React from 'react'
import PropTypes from 'prop-types'
import { IndexPageTemplate } from '../../templates/index-page'

const IndexPagePreview = ({ entry, getAsset, widgetsFor }) => {
  const data = entry.getIn(['data']).toJS()

  let slides1 = widgetsFor('slides').map(function (slide, index) {
    console.log('SLIDE');
    console.log(slide.getIn(['data', 'sidebarDescription']));
    console.log(index);
  })

  console.log('DATA');
  console.log(data);

  //console.log(slides);
  if (data) {
    return (
      <IndexPageTemplate
        image={data.image}
        title={data.title}
        slides={widgetsFor('slides')}
      />
    )
  } else {
    return <div>Loading...</div>
  }
}

IndexPagePreview.propTypes = {
  entry: PropTypes.shape({
    getIn: PropTypes.func,
  }),
  getAsset: PropTypes.func,
}

export default IndexPagePreview

这是我在控制台注销这些东西时得到的数据:

数据

{templateKey: "index-page", title: "Gabler Youngston Website", image: "/img/home/gy_icon_logo.png", slides: Array(2)}
image: "/img/home/gy_icon_logo.png"
slides: Array(2)
0: {}
1: {}
length: 2
__proto__: Array(0)
templateKey: "index-page"
title: "Gabler Youngston Website"
__proto__: Object

以及地图功能中的 SLIDES

SLIDE
IndexPagePreview.js:1 Fe {size: 0, _root: undefined, __ownerID: undefined, __hash: undefined, __altered: false}size: 0__altered: false__hash: undefined__ownerID: undefined_root: undefined__proto__: r
IndexPagePreview.js:1 0

如果我在页面模板中记录相同的道具,它包含数据。我最好的猜测是与事件道具的创建有关/不可变映射不适用于嵌套的东西,除非你在某处定义它。

标签: reactjsgatsbynetlify-cms

解决方案


推荐阅读