首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Gatsby静态/动态混合元件

问Gatsby静态/动态混合元件
EN

Stack Overflow用户
提问于 2018-10-23 23:35:52
回答 1查看 889关注 0票数 1

我在gatsby develop和gatsby build生成的站点之间有一个不一致的行为问题。其结果是一个在开发中而不是生产中工作的网站。

我的网站摘要:

一个简单的类似博客的网站(个人简介,而不是博客帖子)。索引页是人员列表,该列表中的每一项都链接到该人的配置文件页面。

我正在使用盖茨比来构建这个站点。我的数据(个人简介)是托管在内容无头CMS上的条目。我正在使用盖茨比源-内容丰富源代码插件。

问题的高级描述

我无法在索引页面中调整配置文件列表项的顺序。唯一的行为,我的网站超越任何基本盖茨比教程是,我想随机化的配置文件列表在我的索引页面(给每个人一个公平的机会被列在顶端)。

gatsby build生成一个静态索引页,其中列表位于一个置换中。当在浏览器中加载时,ThumbList组件会在呈现时将这些项重新洗牌到另一个排列中,并且一些子元素在其他元素移动时没有得到适当的管理。例如,这会导致将图像与错误的名称配对。

密码

下面的代码为可读性做了一些总结。

src/pages/index.js:

代码语言:javascript
复制
import React from "react"
import Layout from "../components/layout"
import ThumbList from "../components/thumbList"
import { graphql } from "gatsby"

export default ({data}) => {
  // people are called "creators" in the app
  const creatorData = data.allContentfulCreator.edges
  const shuffledData = shuffle(creatorData.slice(0))
    return (
      <Layout>
        <ThumbList data={shuffledData} />
      </Layout>
    )
}

const shuffle = (a) => {
  // Fisher-Yates randomized array in-place shuffle algo
  // ...
  return a
}

export const query = graphql`
  {
    allContentfulCreator {
      edges {
        node {
          id
          slug
          name
          bio {
            id
            bio
          }
          mainImage {
            file {
              url
            }
          }
        }
      }
    }
  }
`

src/components/umbList.js:

代码语言:javascript
复制
import React from "react"
import { Link } from "gatsby"

// A list of creator profile links, with name and picture thumbnail
export default ({data}) => {
  return (
    <div>
      <ul>
        {
          data.map(({node}) => {
            const creator = node
            const link = "/" + creator.slug
            const image = "https:" + creator.mainImage.file.url

            return (
              <li key={creator.id}>
                <Link to={link}>
                  {creator.name}
                </Link>
                <img src={image} />
              </li>
            )
          })
        }
      </ul>
    </div>
  )
}

gatsby build的结果是包含以下内容的index.html:

代码语言:javascript
复制
  <ul>
    <li>
      <a href="/alice">
        Alice
      </a>
      <img src="cdn.com/alice.jpg">
    </li>
    <li>
      <a href="/bob">
        Bob
      </a>
      <img src="cdn.com/bob.jpg">
    </li>
    <li>
      <a href="/eve">
        Eve
      </a>
      <img src="cdn.com/eve.jpg">
    </li>
  </ul>

但是,当在浏览器中(通过gatsby serve或站点的部署版本)查看索引页时,live ThumbList组件再次对其呈现方法中的数据进行洗牌。

结果是重新呈现的html:

代码语言:javascript
复制
  <ul>
    <li>
      <a href="/alice">
        Bob
      </a>
      <img src="cdn.com/alice.jpg">
    </li>
    <li>
      <a href="/bob">
        Eve
      </a>
      <img src="cdn.com/bob.jpg">
    </li>
    <li>
      <a href="/eve">
        Alice
      </a>
      <img src="cdn.com/eve.jpg">
    </li>
  </ul>

这里只有文本节点被重新排列以匹配新的顺序(由记录数组顺序的控制台确认),但是链接和图像元素仍然停留在静态构建中的位置。现在名称、图像和链接都被置乱了。

还有两件事要注意:

  1. 所有这些都可以与gatsby develop一起工作。我想这是因为在开发过程中,index.html是在没有静态内容的情况下生成的--允许从一开始就完全控制DOM,而不需要静态脚手架来混淆它。
  2. 使用react检查器,我看到虚拟DOM和真实DOM已经不同步了。React认为它正确地调整了列表中的项目。检查员展示的情况如下:

(可读性的缩写)

代码语言:javascript
复制
<ul>
    <li key="165e2405">
        <GatsbyLink to="/bob">
            Bob
        </GatsbyLink>
        <img src="cdn.com/bob.jpg"></img>
    </li>
    <li key="067f9afc">
        <GatsbyLink to="/eve">
            Eve
        </GatsbyLink>
        <img src="cdn.com/eve.jpg"></img>
    </li>
    <li key="ca4b82bf">
        <GatsbyLink to="/alice">
            Alice
        </GatsbyLink>
        <img src="cdn.com/alice.jpg"></img>
    </li>
</ul>

我的问题

  1. 这仅仅是一种非盖茨比式的方法吗?这是对“混合应用程序页面”的描述似乎意味着您可以有静态组件或动态组件。我想我试图做到这两种方式:我希望在构建过程中通过graphql从contentful获取概要文件,这样它就可以通过静态HTML +预构建的json数据文件(例如/static/d/556/path---index-6a9-L7r5Sntxcv3RUIoHYIR3Qqm9Jmg.json)获得,但是我想动态地对数据进行洗牌,并在呈现时重新排列DOM。盖茨比不可能这么做吗?我是否需要在构建过程中放弃预取数据,只需要考虑一个动态组件并通过componentDidMount中的内容API获取数据?
  2. 如果这个方法应该是可以的,我做错了什么?
  3. 如果这种方法不是虚无缥缈的,那么是否有办法在构建时修改(洗牌)通过graphql查询的数据?实际上,如果数据只是在构建时重新洗牌,而不是在浏览器中运行时重新洗牌,我会更高兴--我可以每隔一个小时就自动地重建站点,并且网站对客户来说可能更加静态。
EN

回答 1

Stack Overflow用户

发布于 2020-01-07 16:50:15

我最近一直在为这件事苦苦挣扎!

我的解决方案是使用ReactDOM的呈现方法在父组件挂载后呈现被洗牌的内容:

代码语言:javascript
复制
import React, { useRef, useEffect } from "react";
import { render } from "react-dom";
import shuffle from "../utils/shuffle";

const shuffledArray = shuffle(array.slice());

// The below should still be able to work with graphql fetched data
// as I think the array will be saved to a variable for use in the client,
// although in my case I haven't used it so can't be fully sure
const ShuffledJSXElements = () =>
    shuffledArray.map(creator => (
        <li key={creator.id}>
            <Link to={link}>
                  {creator.name}
            </Link>
            <img src={image} />
      </li>
    ));

const Page = () => {
    const shuffledContentContainerRef = useRef();

    useEffect(() => {
        const ontainer = portfolioContainerRef.current;
        render(<ShuffledJSXElements />, container);
    }, []);

    return (
        <MainWrapper>
            <StyledPortfolioGridWrapper ref={shuffledContentContainerRef} />
        </MainWrapper>
    );
};

export default Portfolio;

一个令人沮丧的事情是,容器元素在呈现内容之前不会知道自己的高度,所以布局可能会稍微跳一下。解决此问题的方法是使用min-height css属性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52959147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档