在页面重新加载时,我的 Gatsby.js 页脚组件呈现两次

Posted

技术标签:

【中文标题】在页面重新加载时,我的 Gatsby.js 页脚组件呈现两次【英文标题】:On page reload, my Gatsby.js footer component renders twice 【发布时间】:2020-09-13 20:13:26 【问题描述】:

感谢您花时间查看我的问题。非常感谢任何帮助。

**更新: 好的,所以我想我知道是什么导致了问题,但我不知道为什么。以前,在我的产品/商品页面上,我的数据库中只有一项。在产品/豆类页面上,我有多个项目。在只有一个查询结果的产品/商品页面上,页脚没有显示两次。一旦我在商品类别中添加了另一个商品并且 products/merch 有两个商品,在页面重新加载时它也开始复制页脚。

为什么多个查询会对页面的呈现方式产生任何影响?对此有什么解决方案?我将尝试将数据作为道具从 graphql 传递到 allProducts 组件,看看是否能解决问题。 **

我正在为我正在构建的电子商务网站使用 Gatsby.js 和 Strapi 无头 CMS。在显示特定类别中所有产品的页面上,如果重新加载页面,它会呈现两次页脚。这很令人困惑,因为当页面第一次呈现时它很好,但只有在重新加载时才会这样做。如果网站从该特定页面加载,它还会显示两个页脚。一旦我导航到另一个页面并重新加载,第二个页脚就会消失。这个给我问题的页面有一个 GraphQL 查询。我有另一个页面也有 GraphQL 查询,但它不这样做。此页面中的某些内容导致渲染出现问题。

我尝试过的: 在 gatsby-node.js 中,在 createPages 导出中,我尝试创建每个页面并传递模板和“类型”上下文,以便 GraphQL 查询可以过滤页面所需的数据。我认为以这种方式使用 createPage 可能会导致呈现问题。我还尝试删除 Footer 组件的内容并将它们直接放在 layout.js 中。我试过从页面中删除 Layout 组件并直接添加 Header.js 和 Footer.js ,仍然是同样的问题。我只有在托管它后才遇到这个问题,而不是在本地主机上。是服务器端渲染的问题吗?这是 gatsby cloud 上托管的站点的链接,如果您单击任何其他页面并刷新第二个页脚就会消失,但如果您单击返回此页面然后刷新第二个页脚会再次弹出。

https://build-856af2e5-f049-46de-b6a5-9e11aa46a906.gtsb.io/products/beans/

  createPage(
    path: "/products/merch",
    component: path.resolve(`src/templates/allproducts.js`),
    context: 
      type: "merch",
    ,
  )

  createPage(
    path: "/products/beans",
    component: path.resolve(`src/templates/allproducts.js`),
    context: 
      type: "beans",
    ,
  )

然后我将每个页面移动到 Gatsby pages 文件夹中的一个文件夹中。因此,我没有使用 createPages 以编程方式创建它们,而是通过创建产品文件夹然后为每个类别添加新页面来制作它们。这并没有通过手动创建页面而不是使用 createPages 来解决我的问题。

在我的 layout.js 中为什么页脚会加载两次而不是页眉或主要组件对我来说没有意义,看起来像这样:

import React from "react"
import PropTypes from "prop-types"
import  useStaticQuery, graphql  from "gatsby"
import Footer from "./Footer"
import Header from "./header"
import "./layout.css"

const Layout = ( children ) => 
  const data = useStaticQuery(graphql`
    query SiteTitleQuery 
      site 
        siteMetadata 
          title
        
      
    
  `)

  return (
    <>
      <Header siteTitle=data.site.siteMetadata.title />

      <main>children</main>
      <Footer />
    </>
  )


Layout.propTypes = 
  children: PropTypes.node.isRequired,


export default Layout

这是 Footer.js 组件:

import React from "react"
import  Facebook, Instagram, Twitter  from "@material-ui/icons"
import styled from "styled-components"

const BottomNav = styled.footer`
  border-top: 1px solid black;
  position: sticky;
  height: 15vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  font-family: Raleway;
  text-transform: uppercase;
`

const BottomNavContainer = styled.div`
  display: flex;
  justify-content: space-between;
  width: 200px;
  margin-bottom: 0.3rem;
`

const Footer = () => 
  return (
    <BottomNav>
      <BottomNavContainer>
        <Facebook />
        <Instagram />
        <Twitter />
      </BottomNavContainer>

      <div>
        © new Date().getFullYear(),` ` The Blank
      </div>
    </BottomNav>
  )


export default Footer

这里是复制页脚的页面的代码:

function Alert(props) 
  return <MuiAlert elevation=6 variant="filled" ...props />


const AllBeansPage = props => 
  const products = props.data.allStrapiProduct.nodes
  // const classes = useStyles()
  const [open, setOpen] = React.useState(false)
  const  addToCart  = useContext(CartContext)
  const handleClick = () => 
    setOpen(true)
  

  const handleClose = (event, reason) => 
    if (reason === "clickaway") 
      return
    

    setOpen(false)
  

  return (
    <Layout>
      <SEO
        title=
          products[0].type.charAt(0).toUpperCase() + products[0].type.slice(1)
        
      />
      <Fade in=true timeout= enter: 2000, exit: 500 >
        <AllProductsContainer>
          <Container>
            products.map(product => (
              <Slide
                direction="left"
                in=true
                mountOnEnter
                unmountOnExit
                timeout= enter: 1500, exit: 500 
              >
                <ProductCard key=product.id>
                  <Link
                    key=product.id
                    style=
                    to=`products/$product.type/$product.slug`
                  >
                    <ImageContainer>
                      console.log(product.thumbnail.childImageSharp.fluid)
                      <Img
                        key=product.id
                        fluid=product.thumbnail.childImageSharp.fluid
                      />
                    </ImageContainer>
                  </Link>
                  <ProductContent>
                    <Typography
                      gutterBottom
                      variant="h5"
                      component="h1"
                      style=
                        fontFamily: "Caveat",
                        fontSize: "clamp(22px, 3vw, 28px)",
                      
                    >
                      product.name
                    </Typography>
                    <Typography
                      variant="body2"
                      color="textSecondary"
                      style= fontSize: "clamp(12px, 1.5vw, 16px)" 
                    >
                      product.description.slice(0, 35)...
                    </Typography>

                    <Link
                      key=product.id
                      style=
                      to=`products/$product.type/$product.slug`
                    >
                      " "
                      <Typography
                        variant="subtitle1"
                        color="primary"
                        style= fontSize: "clamp(14px, 1.5w, 18px)" 
                      >
                        Learn More
                      </Typography>
                    </Link>
                  </ProductContent>
                  <CardActionArea>
                    <CardActions
                      style=
                        display: "flex",
                        justifyContent: "space-between",
                      
                    >
                      <Button
                        size="small"
                        color="primary"
                        onClick=() => 
                          addToCart(product, 1)
                          handleClick()
                        
                        style= fontSize: "clamp(12px, 1.5vw, 18px)" 
                      >
                        Add To Cart
                      </Button>
                      <Typography
                        variant="body1"
                        style= fontSize: "clamp(12px, 1.5vw, 18px)" 
                      >
                        formatPrice(product.price_in_cents)
                      </Typography>
                    </CardActions>
                  </CardActionArea>
                </ProductCard>
              </Slide>
            ))
          </Container>
        </AllProductsContainer>
      </Fade>
      <Snackbar open=open autoHideDuration=6000 onClose=handleClose>
        <Alert onClose=handleClose severity="success">
          Item successfully added to cart.
        </Alert>
      </Snackbar>
    </Layout>
  )


export default AllBeansPage

export const productQuery = graphql`
  query allBeanQuery 
    allStrapiProduct(filter:  type:  eq: "beans"  ) 
      nodes 
        strapiId
        id
        description
        created_at
        price_in_cents
        name
        slug
        type
        thumbnail 
          childImageSharp 
            fluid(quality: 100, maxWidth: 150, maxHeight: 150) 
              ...GatsbyImageSharpFluid
            
          
        
      
    
  
`

【问题讨论】:

请添加您的``和&lt;BottomNavContainer&gt;代码 在Footer.js 组件中,顶部是代码。我使用 styled-components 来创建这两个组件。 【参考方案1】:

好的!所以这是解决方案。如果您使用的是 GatsbyJS 和 CMS,如果您使用 Material-UI,有时可能会出现在服务器上渲染内容的问题。我在想 Material-UI 中的某些东西会导致页面上的重新渲染。基本上,在产品页面组件中,我替换了

<Button
    onClick=() => 
    addToCart(product, 1)
    handleClick()
   
  style= fontSize: "clamp(12px, 1.5vw, 16px)" >ADD TO CART
 </Button>

<div
    onClick=() => 
    addToCart(product, 1)
    handleClick()
   
  style= fontSize: "clamp(12px, 1.5vw, 16px)" >ADD TO CART
</div>

然后它起作用了。因此,如果您在一个页面上呈现两个相同的组件并且一切看起来都正确,请仔细检查您正在使用的组件库是否导致问题。

【讨论】:

以上是关于在页面重新加载时,我的 Gatsby.js 页脚组件呈现两次的主要内容,如果未能解决你的问题,请参考以下文章

Facebook 页脚栏是一个 iframe,那么为啥它不与页面的其余部分一起重新加载呢?

Gatsby - 加载(静态查询)白屏

Codeigniter 加载页眉和页脚一次

在购物车页脚中重新加载 PHP If/Else 语句而不重新加载整个页面? ( XT 浮动车)

嵌套反应路由器组件不会在页面重新加载时加载/渲染?

Jquery Ajax加载除某个div之外的整个页面