【问题标题】:gatsby + react hook masonry breaks on build because there is no windowgatsby + react hook masonry 在构建时中断,因为没有窗口
【发布时间】:2020-05-07 16:22:53
【问题描述】:

我设置了一个反应挂钩来处理我的 gatsby 网站某些页面上的砌体。问题是它引用了窗口对象,该对象在服务器端gatsby build 上不存在。 I've read that the solution is to wrap useEffect with:

if (typeof window === 'undefined') {
}

但是我似乎无法包装我的砌体文件的正确部分。我还读到使用上述技巧会使服务器端渲染变得毫无意义,不确定。

有人能告诉我 if 语句应该放在我下面的砌体文件中的什么位置吗?它不是一个插件,它是我的 utils 文件夹中的一个钩子。 Using code from this tut。我已经尝试了 useEffects 中的 if 语句,围绕 useEffects,围绕整个 eventListener,但没有骰子。谢谢!!

import React, { useEffect, useRef, useState } from "react"
import styled from "styled-components"

const useEventListener = (eventName, handler, element = window) => {
  const savedHandler = useRef()

  useEffect(() => {
    savedHandler.current = handler
  }, [handler])

  useEffect(() => {
    const isSupported = element && element.addEventListener
    if (!isSupported) return

    const eventListener = event => savedHandler.current(event)
    element.addEventListener(eventName, eventListener)

    return () => {
      element.removeEventListener(eventName, eventListener)
    }
  }, [eventName, element])
}

const fillCols = (children, cols) => {
  children.forEach((child, i) => cols[i % cols.length].push(child))
}

export default function Masonry({ children, gap, minWidth = 500, ...rest }) {
  const ref = useRef()
  const [numCols, setNumCols] = useState(3)
  const cols = [...Array(numCols)].map(() => [])
  fillCols(children, cols)

  const resizeHandler = () =>
    setNumCols(Math.ceil(ref.current.offsetWidth / minWidth))
  useEffect(resizeHandler, [])
  useEventListener(`resize`, resizeHandler)

  const MasonryDiv = styled.div`
    margin: 1rem auto;
    display: grid;
    grid-auto-flow: column;
    grid-gap: 1rem;
  `
  const Col = styled.div`
    display: grid;
    grid-gap: 1rem;
  `

  return (
    <MasonryDiv ref={ref} gap={gap} {...rest}>
      {[...Array(numCols)].map((_, index) => (
        <Col key={index} gap={gap}>
          {cols[index]}
        </Col>
      ))}
    </MasonryDiv>
  )
}

【问题讨论】:

  • 你可能想使用 masonic 或 react-masonry-component 之类的东西,而不是尝试在 React 中重新实现 Masonry。
  • 我想要一种特定类型的柱状砌体,但 div 按时间顺序从左到右阅读,否则会完全使用它
  • 啊,有趣!

标签: reactjs window react-hooks gatsby


【解决方案1】:

在您的gatsby-node.js 中添加以下 sn-p:

exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
  if (stage === "build-html") {
    actions.setWebpackConfig({
      module: {
        rules: [
          {
            test: /masonry/,
            use: loaders.null(),
          },
        ],
      },
    })
  }
}

注意:使用 node_modules 中的 /masonry/ 库路径。

来自关于 debugging HTML builds 的 Gatsby 文档:

构建静态 HTML 文件时的错误通常发生在以下情况之一 原因如下:

您的一些代码引用了“浏览器全局变量”,例如 window 或 文档。如果这是您的问题,您应该会看到上面的错误,例如 “window 未定义”。要解决此问题,请找到有问题的代码并 a)在调用代码之前检查是否定义了窗口,因此 代码在 Gatsby 构建时不运行(参见下面的代码示例)或 b) 如果代码在 React.js 组件的渲染函数中,移动 将该代码放入 componentDidMount 生命周期或 useEffect 挂钩中, 这确保代码不会运行,除非它在浏览器中。

或者,您可以将您的 Masonry 钩子用法包含在此语句中:

if (typeof window !== `undefined`) {
  const module = require("module")
}

注意!== 的比较,而不是您提供的===。

【讨论】:

  • 砌体钩子不是节点库,它是我的 utils/ 文件夹中的一个 js 文件,当我填充测试时:使用 utils/masonry.js 它不起作用?这是我正在使用的砖石系统janosh.io/blog/react-hooks-masonry
  • 尝试将您的 Masonry hook 用法包含在我添加的比较中 (typeof window !== 'undefined')。
  • @FerranBuireu,您也可以查看并回答我的问题吗? stackoverflow.com/questions/66958067/…
猜你喜欢
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
  • 2021-11-25
  • 1970-01-01
  • 2018-11-24
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
相关资源
最近更新 更多