首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React/Gatsby/Chakra UI中的窗口

React/Gatsby/Chakra UI中的窗口
EN

Stack Overflow用户
提问于 2021-10-05 09:53:25
回答 1查看 217关注 0票数 1

我有一个使用React,Gatsby和Chakra UI框架的简单web应用程序。这个应用程序由一个索引页组成,它从1000+ mdx文件中查询头条,并呈现一个最小的摘要组件,其中有5个来自头条的字段和一个指向每个字段的详细页面的链接。1000+详细页面是使用createPage在gatsby-node.js中生成的。

索引页面使用map遍历每个mdx节点,并使用Chakra UI简单网格以及每个项目的其他Chakra组件。

将应用程序部署到Gatsby Cloud时收到的灯塔报告将应用程序的性能评分为60/100,这主要是由于DOM中的元素过多(由索引页面呈现的1000+摘要元素)。

我已经查看了所有相关的文档,并在其他来源中进行了搜索,但是没有找到可行的解决方案,可以只呈现在屏幕上显示的大约25个项目的html,并根据需要呈现其余的项目,而不是从一开始就呈现所有的1000+。

代码语言:javascript
复制
import * as React from "react";
import { ChakraProvider, chakra, Box, SimpleGrid, HStack, Button, VStack, Wrap, WrapItem, Badge } from "@chakra-ui/react";
import { graphql, useStaticQuery } from 'gatsby';

const IndexPage = () => {

    const query = useStaticQuery(graphql` 
    query AllObjects {
      allMdx(sort: {fields: frontmatter___field1}) {
        nodes {
          frontmatter {
            field1
            field2
            field3
            field4
            field5
            field6
            field7
            uniqueId
          }
        }
      }
    }
    `)

    return (
      <ChakraProvider>
        <body>
            <main>
                      <SimpleGrid columns={{base: 1, lg: 3, md: 2, sm:1}} spacing={{base: '1.5em', lg: '1.5em', md:'1.0', sm:'0.90em'}}>
                      { query.allMdx.nodes.map((node) => (
                          <Box key={node.frontmatter.field1} margin="2em" padding="1em">
                            <HStack padding="0.4em" align="center" alignItems="stretch" justifyContent="space-between">
                            <Button size="sm" shadow="md" colorScheme="blue"
                            onClick={(e) => {
                              e.preventDefault();
                              window.location.href=`/objects/${node.frontmatter.field1.toLowerCase()}`;
                              }}
                            >Detail</Button>
                            <Box align="center"/>
                            <VStack alignItems="end" justifyContent="right">
                            <Wrap columns={2} spacing={1} direction={["row-reverse"]} isInline="true" shouldWrapChildren="true">
                              <WrapItem>
                                {node.frontmatter.field5 === true &&
                                <Badge colorScheme="green">Field5</Badge>
                                }
                              </WrapItem>
                              <WrapItem>
                                {node.frontmatter.field6 === true &&
                                <Badge colorScheme="blue">Field6</Badge>
                                }
                              </WrapItem>
                              <WrapItem>
                                {node.frontmatter.field7 === true &&
                                <Badge colorScheme="orange">field7</Badge>
                                }
                              </WrapItem>
                              <WrapItem>
                                {node.frontmatter.field4 === true &&
                                <Badge colorScheme="red">Field8</Badge>
                                }
                              </WrapItem>
                            </Wrap>
                            </VStack>
                            </HStack>
                            <Box bg="gray.300" borderRadius="0.5em" margin="0em" padding="0em">
                            <chakra.h2 id={node.frontmatter.field1.toLowerCase()}>
                              Field1: {node.frontmatter.field1}
                            </chakra.h2>
                            <chakra.p>Field2: {node.frontmatter.field2}</chakra.p>
                            <chakra.p>{node.frontmatter.field3}</chakra.p>
                            </Box>
                          </Box>
                      ))}
                      </SimpleGrid>

            </main>
        </body>
      </ChakraProvider>
    )
  };

export default IndexPage;
EN

回答 1

Stack Overflow用户

发布于 2021-10-05 13:18:59

好了,你找到了解决方案。使用无限滚动或一些类似的延迟(按钮等)方法来按需呈现全部网格项目,而不是同时呈现所有网格项目。

只需创建一个包含元素切片数量的状态(useState),并在用户滚动页面时立即升级它们。这将保存(并延迟)初始的DOM元素。

我将添加一个基于按钮的方法来渲染更多的元素,但是使用无限滚动的想法是完全相同的。

代码语言:javascript
复制
const IndexPage = () => {
    const query = useStaticQuery(graphql` 
    query AllObjects {
      allMdx(sort: {fields: frontmatter___field1}) {
        nodes {
          frontmatter {
            field1
            field2
            field3
            field4
            field5
            field6
            field7
            uniqueId
          }
        }
      }
    }
    `)
  // Array of all news articles
  const allGridElements = query.allMdx.nodes

  // State for the list
  const [list, setList] = useState([...allGridElements.slice(0, 10)])

  // State to trigger the load more
  const [loadMore, setLoadMore] = useState(false)

  // State of whether there is more to load
  const [hasMore, setHasMore] = useState(allGridElements.length > 10)

  // Load more button click
  const handleLoadMore = () => {
    setLoadMore(true)
  }

  // Handle loading more articles
  useEffect(() => {
    if (loadMore && hasMore) {
      const currentLength = list.length
      const isMore = currentLength < allGridElements.length
      const nextResults = isMore
        ? allGridElements.slice(currentLength, currentLength + 10)
        : []
      setList([...list, ...nextResults])
      setLoadMore(false)
    }
  }, [loadMore, hasMore]) //eslint-disable-line

  //Check if there is more
  useEffect(() => {
    const isMore = list.length < allGridElements.length
    setHasMore(isMore)
  }, [list]) //eslint-disable-line

  return (
    <div>
      <h1>Load more demo</h1>
      <div>
        {list.map((item) => (
        { /* Your JSX rendering the grid items */ }
        ))}
      </div>
      {hasMore ? (
        <button onClick={handleLoadMore}>Load More</button>
      ) : (
        <p>No more results</p>
      )}
    </div>
  )
}

export default IndexPage

注意:为了避免无休止的回答,我省略了您的循环返回的JSX。只要把它放在评论里就行了。

这是不言而喻的,您将所有元素设置为React状态(useState)并遍历它。useEffect负责根据监听器更新列表。

其他有用的资源:

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

https://stackoverflow.com/questions/69448329

复制
相关文章

相似问题

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