【问题标题】:How to randomly render Contentful data to div onClick using React/GatsbyJS如何使用 React/GatsbyJS 将 Contentful 数据随机呈现到 div onClick
【发布时间】:2020-06-29 21:49:37
【问题描述】:

盖茨比/反应菜鸟在这里。

我在 Contentful 中创建了一个名为 Topic 的内容类型。每个主题都包含一个标题、描述和主题页面的 slug。目前,我能够将每个主题呈现为页面上的卡片。我现在想弄清楚的是如何一次只渲染一张卡片,并在点击旋转按钮时让卡片内容(标题/描述)随机变化。

我创建了这个快速demo 以直观地展示我的目标。

这里是我渲染每个主题卡的地方:

import React from 'react'
import { graphql, navigate, StaticQuery } from 'gatsby'
import './topicFeed.scss'

export default () => (
   <StaticQuery
     query={graphql` 
     query TopicFeed {
  allContentfulTopic(filter: {featured: {eq: true}}) {
    edges {
      node {
        cardDescription {
          cardDescription
        }
        cardTitle
        id
        slug
      }
    }
  }
}
`}   
     render={data => ( 
      
          <div>
            <div className='feed'>
                {data.allContentfulTopic.edges.map(edge => (
                <div key={edge.node.id} className='topic__item'>
                    <h2 className='card__title'>{edge.node.cardTitle}</h2>
                    <div className="card__desc--container">
                        <p className='card__desc'>{edge.node.cardDescription.cardDescription}</p>
                    </div>
                    <div className='card__link' onClick={() => navigate(`/topic/${edge.node.slug}`)}>
                        <p>Learn More</p>
                    </div>
                </div>
                ))}
            </div>

            <button onClick={() =>console.log('werked')}onClick={() =>console.log('werked')}>SPIN</button>
        </div>
     )}
   />
 )

据我了解,gatsby 会在构建时为每张卡片呈现 div,因此我对用户如何在点击时操作这些数据感到困惑。

【问题讨论】:

  • Gatsby 不需要预先“构建”所有不同的卡片,它只会为页面路由创建静态标记,没有什么可以阻止您一次显示一张卡片并拥有它在点击时随机化。您的页面已经获取了完整的数据列表,但您正在使用 .map() 来呈现数组中的所有卡片。您可能只想按数组索引抓取一张卡片,您可以根据数组长度使用Math.random() 选择它。

标签: reactjs gatsby contentful headless-cms jamstack


【解决方案1】:

试试这样的。与其映射整个卡片数组,不如只显示一个索引。当按钮被点击时,设置一个随机卡片索引。

import React, { useState } from 'react'
import { graphql, navigate, StaticQuery } from 'gatsby'
import './topicFeed.scss'

export default () => {
  const [cardIndex, setCardIndex] = useState(0)

  const getRandomCardIndexBetween = (min, max) => Math.floor(Math.random() * (Math.floor(max) - Math.ceil(min) + 1)) + min

  return (
    <StaticQuery
      query={graphql` 
          query TopicFeed {
              allContentfulTopic(filter: {featured: {eq: true}}) {
                  edges {
                      node {
                          cardDescription {
                              cardDescription
                          }
                          cardTitle
                          id
                          slug
                      }
                  }
              }
          }
      `}
      render={data => {
        const {
          cardDescription: {
            cardDescription
          },
          cardTitle,
          slug,
        } = data.allContentfulTopic.edges[cardIndex].node;

        return (
          <div>
            <div className='feed'>
              <div className='topic__item'>
                <h2 className='card__title'>{cardTitle}</h2>
                <div className="card__desc--container">
                  <p className='card__desc'>{cardDescription}</p>
                </div>
                <div className='card__link' onClick={() => navigate(`/topic/${slug}`)}>
                  <p>Learn More</p>
                </div>
              </div>
            </div>

            <button onClick={setCardIndex(getRandomCardIndexBetween(0, data.allContentfulTopic.edges.length - 1))}>SPIN</button>
          </div>
        )}}
    />
  )
}

这是一个jsfiddle,展示了如何使用普通的 React(没有 Gatsby/GraphQL)实现这一目标

【讨论】:

  • 您的解决方案是有道理的(为此),但是当我实施它时,我收到此错误:错误:对象作为 React 子项无效(找到:带有键 {node} 的对象)。如果您打算渲染一组子项,请改用数组。
  • 抱歉,代码未经测试。你最后找到解决办法了吗?您应该可以像data.allContentfulTopic.edges[cardIndex] 一样直接使用数组索引,也可以使用对象解构来整理一下。将更新我的答案。
猜你喜欢
  • 2018-07-12
  • 1970-01-01
  • 2021-11-20
  • 2018-05-28
  • 2016-11-21
  • 2020-05-20
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多