在创建我的 gatsby-node.js 文件并正确指示通过 graphql 动态生成的页面后,我无法查看任何详细产品
After creating my gatsby-node.js file with the pages properly instructed to be dynamically generated via graphql, I can't view any of detailed product
如果我点击某个产品,我会收到以下 404 错误:
如果我点击引导我进入上面屏幕截图中列出的 link 的前 6 个产品之一,我会收到关于我的数量未定义的错误消息,如下所示:
当我关闭错误时,我留下了这个:
再次 - 我在下面包含了我的 gatsby-node.js 以及我的 QtyButton.js 代码...我还有 linked to my github repo here with the most updated code...
盖茨比-node.js:
/**
* Implement Gatsby's Node APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/node-apis/
*/
// You can delete this file if you're not using it
exports.createPages = async({
graphql,
actions
}) => {
const {
createPage
} = actions
const result = await graphql(
`
{
products: allStrapiProduct {
edges {
node {
name
strapiId
description
category {
name
}
variants {
id
color
size
style
price
images {
localFile {
childImageSharp {
gatsbyImageData
}
}
}
}
}
}
}
categories: allStrapiCategory {
edges {
node {
strapiId
name
description
filterOptions {
Size {
checked
label
}
Style {
checked
label
}
Color {
checked
label
}
}
}
}
}
}
`
)
if (result.errors) {
throw result.errors
}
const products = result.data.products.edges
const categories = result.data.categories.edges
products.forEach(product => {
createPage({
path: `/${product.node.category.name.toLowerCase()}/${
product.node.name.split(' ')[0]
}`,
component: require.resolve('./src/templates/ProductDetail.js'),
context: {
name: product.node.name,
id: product.node.strapiId,
category: product.node.category.name,
description: product.node.description,
variants: product.node.variants,
product,
},
})
})
categories.forEach(category => {
createPage({
path: `/${category.node.name.toLowerCase()}`,
component: require.resolve('./src/templates/ProductList.js'),
context: {
name: category.node.name,
description: category.node.description,
id: category.node.strapiId,
filterOptions: category.node.filterOptions,
},
})
})
}
exports.onCreateWebpackConfig = ({
stage,
loaders,
actions
}) => {
if (stage === 'build-html') {
actions.setWebpackConfig({
module: {
rules: [{
test: /react-spring-3d-carousel/,
use: loaders.null()
}],
},
})
}
}
QtyButton.js
import React, {
useState,
useEffect,
useContext
} from 'react'
import clsx from 'clsx'
import Grid from '@material-ui/core/Grid'
import Typography from '@material-ui/core/Typography'
import Button from '@material-ui/core/Button'
import ButtonGroup from '@material-ui/core/ButtonGroup'
import Badge from '@material-ui/core/Badge'
import {
makeStyles
} from '@material-ui/core/styles'
import {
CartContext
} from '../../contexts'
import {
addToCart,
removeFromCart
} from '../../contexts/actions'
import Cart from '../../images/Cart'
const useStyles = makeStyles(theme => ({
qtyText: {
color: ({
white
}) => (white ? theme.palette.secondary.main : '#fff'),
},
mainGroup: {
height: '3rem',
},
editButtons: {
height: '1.525rem',
borderRadius: 0,
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.main,
borderLeft: ({
white
}) =>
`2px solid ${white ? theme.palette.secondary.main : '#fff'}`,
borderRight: ({
round
}) => (round ? 0 : '2px solid #fff'),
borderBottom: 'none',
borderTop: 'none',
borderRadius: ({
round
}) => (round ? '0px 50px 50px 0px' : 0),
'&:hover': {
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.light,
},
},
endButtons: {
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.main,
borderRadius: 50,
border: 'none',
},
cartButton: {
marginLeft: '0 !important',
transition: 'background-color 1s ease',
},
minus: {
marginTop: '-0.25rem',
},
minusButton: {
borderTop: ({
white
}) =>
`2px solid ${white ? theme.palette.secondary.main : '#fff'}`,
},
qtyButton: {
'&:hover': {
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.main,
},
},
badge: {
color: '#fff',
fontSize: '1.5rem',
backgroundColor: theme.palette.secondary.main,
padding: 0,
},
success: {
backgroundColor: theme.palette.success.main,
'&:hover': {
backgroundColor: theme.palette.success.main,
},
},
}))
export default function QtyButton({
stock,
variants,
selectedVariant,
name,
isCart,
white,
hideCartButton,
round,
override,
}) {
const {
cart,
dispatchCart
} = useContext(CartContext)
const existingItem = isCart ?
cart.find(item => item.variant === variants[selectedVariant]) :
null
const classes = useStyles({
white,
round
})
const [qty, setQtyState] = useState(isCart ? existingItem.qty : 1)
const [success, setSuccess] = useState(false)
let setQty
if (override) {
setQty = val => {
override.setValue(val)
setQtyState(val)
}
} else {
setQty = setQtyState
}
const handleChange = direction => {
if (qty === stock[selectedVariant].qty && direction === 'up') {
return null
}
if (qty === 1 && direction === 'down') {
return null
}
const newQty = direction === 'up' ? qty + 1 : qty - 1
setQty(newQty)
if (isCart) {
if (direction === 'up') {
dispatchCart(addToCart(variants[selectedVariant], 1, name))
} else if (direction === 'down') {
dispatchCart(removeFromCart(variants[selectedVariant], 1))
}
}
}
const handleCart = () => {
setSuccess(true)
dispatchCart(
addToCart(
variants[selectedVariant],
qty,
name,
stock[selectedVariant].qty
)
)
}
useEffect(() => {
if (stock === null || stock === -1) {
return undefined
}
if (qty === 0 && stock[selectedVariant].qty !== 0) {
setQty(1)
} else if (qty > stock[selectedVariant].qty) {
setQty(stock[selectedVariant].qty)
}
}, [stock, selectedVariant])
useEffect(() => {
let timer
if (success) {
timer = setTimeout(() => setSuccess(false), 1500)
}
return () => clearTimeout(timer)
}, [success])
return ( <
Grid item >
<
ButtonGroup classes = {
{
root: classes.mainGroup
}
} >
<
Button classes = {
{
root: clsx(classes.endButtons, classes.qtyButton)
}
} >
<
Typography variant = "h3"
classes = {
{
root: classes.qtyText
}
} > {
qty
} <
/Typography> <
/Button> <
ButtonGroup orientation = "vertical" >
<
Button onClick = {
() => handleChange('up')
}
classes = {
{
root: classes.editButtons
}
} >
<
Typography variant = "h3"
classes = {
{
root: classes.qtyText
}
} >
+
<
/Typography> <
/Button> <
Button onClick = {
() => handleChange('down')
}
classes = {
{
root: clsx(classes.editButtons, classes.minusButton)
}
} >
<
Typography variant = "h3"
classes = {
{
root: clsx(classes.qtyText, classes.minus)
}
} >
-
<
/Typography> <
/Button> <
/ButtonGroup> {
hideCartButton ? null : ( <
Button onClick = {
handleCart
}
disabled = {
stock ? stock[selectedVariant].qty === 0 : true
}
classes = {
{
root: clsx(classes.endButtons, classes.cartButton, {
[classes.success]: success,
}),
}
} >
{
success ? ( <
Typography variant = "h3"
classes = {
{
root: classes.qtyText
}
} > ✓
<
/Typography>
) : ( <
Badge overlap = "circle"
badgeContent = "+"
classes = {
{
badge: classes.badge
}
} >
<
Cart color = "#fff" / >
<
/Badge>
)
} <
/Button>
)
} <
/ButtonGroup> <
/Grid>
)
}
不可能遵循此代码,您粘贴的是图像而不是代码块,因此很难知道每个部分所属的位置(如果它们是在快照之间重复的部分则更难)。尝试调试并添加有趣的部分,而不是整个文件...
and when i close out of the error I am left with this
好吧,你永远不应该关闭这个问题。它需要修复,而不是忽略。
你的gatsby-node.js
,在查询一堆你不使用的字段(图片、价格等)中看起来还不错。请记住,gatsby-node.js
是您创建页面并将数据发送到模板的地方,不要查询不必要的字段以避免构建时间过长。您应该在模板查询中查询这些字段。
说到关于“第一期”,如果你的产品页面没有呈现,那就是你的问题。 运行 gatsby clean
在每个试验中。
关于您的阻塞问题,正如我所说,一个是破坏您的代码,鉴于您提供的详细信息,不可能跟踪跟踪,但我会尝试类似的方法:
<Button
onClick={handleCart}
disabled={stock[selectedVariant] ? stock[selectedVariant].qty === 0 : true}
classes={{
root: clsx(classes.endButtons, classes.cartButton, {
[classes.success]: success,
}),
}}
>
显然,在您的某些产品中,stock
对象中没有 qty
属性,这就是您的代码出错的原因。您应该拉动线程以了解该产品是否应该具有 qty
并将代码逻辑调整为该业务逻辑,而不是其他方式。上面的代码片段应该可以解决您的代码破坏问题,但您需要知道您的 Button
是否应该或不应该 qty
在这一点上。
如果您使用可选的链接插件,您可以将其简化为:
disabled={stock?.selectedVariant?.qty === 0 : true}
如果我点击某个产品,我会收到以下 404 错误:
如果我点击引导我进入上面屏幕截图中列出的 link 的前 6 个产品之一,我会收到关于我的数量未定义的错误消息,如下所示:
当我关闭错误时,我留下了这个:
再次 - 我在下面包含了我的 gatsby-node.js 以及我的 QtyButton.js 代码...我还有 linked to my github repo here with the most updated code...
盖茨比-node.js:
/**
* Implement Gatsby's Node APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/node-apis/
*/
// You can delete this file if you're not using it
exports.createPages = async({
graphql,
actions
}) => {
const {
createPage
} = actions
const result = await graphql(
`
{
products: allStrapiProduct {
edges {
node {
name
strapiId
description
category {
name
}
variants {
id
color
size
style
price
images {
localFile {
childImageSharp {
gatsbyImageData
}
}
}
}
}
}
}
categories: allStrapiCategory {
edges {
node {
strapiId
name
description
filterOptions {
Size {
checked
label
}
Style {
checked
label
}
Color {
checked
label
}
}
}
}
}
}
`
)
if (result.errors) {
throw result.errors
}
const products = result.data.products.edges
const categories = result.data.categories.edges
products.forEach(product => {
createPage({
path: `/${product.node.category.name.toLowerCase()}/${
product.node.name.split(' ')[0]
}`,
component: require.resolve('./src/templates/ProductDetail.js'),
context: {
name: product.node.name,
id: product.node.strapiId,
category: product.node.category.name,
description: product.node.description,
variants: product.node.variants,
product,
},
})
})
categories.forEach(category => {
createPage({
path: `/${category.node.name.toLowerCase()}`,
component: require.resolve('./src/templates/ProductList.js'),
context: {
name: category.node.name,
description: category.node.description,
id: category.node.strapiId,
filterOptions: category.node.filterOptions,
},
})
})
}
exports.onCreateWebpackConfig = ({
stage,
loaders,
actions
}) => {
if (stage === 'build-html') {
actions.setWebpackConfig({
module: {
rules: [{
test: /react-spring-3d-carousel/,
use: loaders.null()
}],
},
})
}
}
QtyButton.js
import React, {
useState,
useEffect,
useContext
} from 'react'
import clsx from 'clsx'
import Grid from '@material-ui/core/Grid'
import Typography from '@material-ui/core/Typography'
import Button from '@material-ui/core/Button'
import ButtonGroup from '@material-ui/core/ButtonGroup'
import Badge from '@material-ui/core/Badge'
import {
makeStyles
} from '@material-ui/core/styles'
import {
CartContext
} from '../../contexts'
import {
addToCart,
removeFromCart
} from '../../contexts/actions'
import Cart from '../../images/Cart'
const useStyles = makeStyles(theme => ({
qtyText: {
color: ({
white
}) => (white ? theme.palette.secondary.main : '#fff'),
},
mainGroup: {
height: '3rem',
},
editButtons: {
height: '1.525rem',
borderRadius: 0,
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.main,
borderLeft: ({
white
}) =>
`2px solid ${white ? theme.palette.secondary.main : '#fff'}`,
borderRight: ({
round
}) => (round ? 0 : '2px solid #fff'),
borderBottom: 'none',
borderTop: 'none',
borderRadius: ({
round
}) => (round ? '0px 50px 50px 0px' : 0),
'&:hover': {
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.light,
},
},
endButtons: {
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.main,
borderRadius: 50,
border: 'none',
},
cartButton: {
marginLeft: '0 !important',
transition: 'background-color 1s ease',
},
minus: {
marginTop: '-0.25rem',
},
minusButton: {
borderTop: ({
white
}) =>
`2px solid ${white ? theme.palette.secondary.main : '#fff'}`,
},
qtyButton: {
'&:hover': {
backgroundColor: ({
white
}) =>
white ? '#fff' : theme.palette.secondary.main,
},
},
badge: {
color: '#fff',
fontSize: '1.5rem',
backgroundColor: theme.palette.secondary.main,
padding: 0,
},
success: {
backgroundColor: theme.palette.success.main,
'&:hover': {
backgroundColor: theme.palette.success.main,
},
},
}))
export default function QtyButton({
stock,
variants,
selectedVariant,
name,
isCart,
white,
hideCartButton,
round,
override,
}) {
const {
cart,
dispatchCart
} = useContext(CartContext)
const existingItem = isCart ?
cart.find(item => item.variant === variants[selectedVariant]) :
null
const classes = useStyles({
white,
round
})
const [qty, setQtyState] = useState(isCart ? existingItem.qty : 1)
const [success, setSuccess] = useState(false)
let setQty
if (override) {
setQty = val => {
override.setValue(val)
setQtyState(val)
}
} else {
setQty = setQtyState
}
const handleChange = direction => {
if (qty === stock[selectedVariant].qty && direction === 'up') {
return null
}
if (qty === 1 && direction === 'down') {
return null
}
const newQty = direction === 'up' ? qty + 1 : qty - 1
setQty(newQty)
if (isCart) {
if (direction === 'up') {
dispatchCart(addToCart(variants[selectedVariant], 1, name))
} else if (direction === 'down') {
dispatchCart(removeFromCart(variants[selectedVariant], 1))
}
}
}
const handleCart = () => {
setSuccess(true)
dispatchCart(
addToCart(
variants[selectedVariant],
qty,
name,
stock[selectedVariant].qty
)
)
}
useEffect(() => {
if (stock === null || stock === -1) {
return undefined
}
if (qty === 0 && stock[selectedVariant].qty !== 0) {
setQty(1)
} else if (qty > stock[selectedVariant].qty) {
setQty(stock[selectedVariant].qty)
}
}, [stock, selectedVariant])
useEffect(() => {
let timer
if (success) {
timer = setTimeout(() => setSuccess(false), 1500)
}
return () => clearTimeout(timer)
}, [success])
return ( <
Grid item >
<
ButtonGroup classes = {
{
root: classes.mainGroup
}
} >
<
Button classes = {
{
root: clsx(classes.endButtons, classes.qtyButton)
}
} >
<
Typography variant = "h3"
classes = {
{
root: classes.qtyText
}
} > {
qty
} <
/Typography> <
/Button> <
ButtonGroup orientation = "vertical" >
<
Button onClick = {
() => handleChange('up')
}
classes = {
{
root: classes.editButtons
}
} >
<
Typography variant = "h3"
classes = {
{
root: classes.qtyText
}
} >
+
<
/Typography> <
/Button> <
Button onClick = {
() => handleChange('down')
}
classes = {
{
root: clsx(classes.editButtons, classes.minusButton)
}
} >
<
Typography variant = "h3"
classes = {
{
root: clsx(classes.qtyText, classes.minus)
}
} >
-
<
/Typography> <
/Button> <
/ButtonGroup> {
hideCartButton ? null : ( <
Button onClick = {
handleCart
}
disabled = {
stock ? stock[selectedVariant].qty === 0 : true
}
classes = {
{
root: clsx(classes.endButtons, classes.cartButton, {
[classes.success]: success,
}),
}
} >
{
success ? ( <
Typography variant = "h3"
classes = {
{
root: classes.qtyText
}
} > ✓
<
/Typography>
) : ( <
Badge overlap = "circle"
badgeContent = "+"
classes = {
{
badge: classes.badge
}
} >
<
Cart color = "#fff" / >
<
/Badge>
)
} <
/Button>
)
} <
/ButtonGroup> <
/Grid>
)
}
不可能遵循此代码,您粘贴的是图像而不是代码块,因此很难知道每个部分所属的位置(如果它们是在快照之间重复的部分则更难)。尝试调试并添加有趣的部分,而不是整个文件...
and when i close out of the error I am left with this
好吧,你永远不应该关闭这个问题。它需要修复,而不是忽略。
你的gatsby-node.js
,在查询一堆你不使用的字段(图片、价格等)中看起来还不错。请记住,gatsby-node.js
是您创建页面并将数据发送到模板的地方,不要查询不必要的字段以避免构建时间过长。您应该在模板查询中查询这些字段。
说到关于“第一期”,如果你的产品页面没有呈现,那就是你的问题。 运行 gatsby clean
在每个试验中。
关于您的阻塞问题,正如我所说,一个是破坏您的代码,鉴于您提供的详细信息,不可能跟踪跟踪,但我会尝试类似的方法:
<Button
onClick={handleCart}
disabled={stock[selectedVariant] ? stock[selectedVariant].qty === 0 : true}
classes={{
root: clsx(classes.endButtons, classes.cartButton, {
[classes.success]: success,
}),
}}
>
显然,在您的某些产品中,stock
对象中没有 qty
属性,这就是您的代码出错的原因。您应该拉动线程以了解该产品是否应该具有 qty
并将代码逻辑调整为该业务逻辑,而不是其他方式。上面的代码片段应该可以解决您的代码破坏问题,但您需要知道您的 Button
是否应该或不应该 qty
在这一点上。
如果您使用可选的链接插件,您可以将其简化为:
disabled={stock?.selectedVariant?.qty === 0 : true}