Как создавать динамические компоненты

Я вижу возможность минимизировать передачу сетевых байтов моего веб-сайта, но не могу найти подходящего решения.

В Gatsby я использую файлы .mdx. В этих файлах я могу использовать компоненты React, такие как: <Cards id = "id_1" />

В файле .json определены десятки карточек, которые можно использовать на веб-сайте, просто вызвав этот компонент в файле mdx и передав их идентификатор.

Компонент «Карты» выглядит примерно так:

import React from 'react'
import Img from 'gatsby-image';
import { StaticQuery, graphql } from 'gatsby';


const Cards = (props) => {
    const card_id = props.id ? props.id.slice(0, 2) : []  // grab id

    return <StaticQuery
        query = {graphql`
        query Query  {
                    images: allFile(filter: { sourceInstanceName: { eq: "card-images" } }) {
                        edges {
                            node {
                                childImageSharp {
                                    fluid(maxHeight: 256, quality: 100) {
                                        ...GatsbyImageSharpFluid_withWebp
                                        ...GatsbyImageSharpFluidLimitPresentationSize
                                    }
                                }
                                name
                            }
                        }
                    }
                    allCardsJson {
                        nodes {
                            name
                            id
                        }
                    }
                }
        `}
        render = {(data) => {
            
            return(
               // returns a component by filtering 'data' by 'card_id'
            )
        }}
    />
}

Все работает нормально, но...

При использовании этого компонента полный результат StaticQuery (имеется в виду: все карточки, так как фильтрация выполняется внутри возврата, а не внутри статического запроса) отправляется посетителям страницы. Это не нужно и приводит к пустой трате пропускной способности сети, потому что, например, на странице используется только одна карта (или несколько).

Я понимаю, что StaticQuery является... статическим. Таким образом, я не могу динамически фильтровать в этом запросе, чтобы ограничить размер результата.

DynamicQuery используются при построении страниц, а не внутри компонентов.

Можно ли каким-то образом создавать компоненты с динамическим содержимым (определенным где-то еще), но ограничиваться только необходимыми данными? (например, предоставив идентификатор, как я пробовал)

Я думаю о создании отдельного файла для каждой карты. Затем импортируйте необходимые карты в файл mdx и передайте его компоненту. Мысли?

Документации по моему варианту использования нет. Это заставляет меня задаться вопросом, использую ли я его по назначению.

🤔 А знаете ли вы, что...
JavaScript был первоначально создан для улучшения интерактивности веб-страниц.


494
2

Ответы:

Запросы GraphQL выполняются ОДИН РАЗ, когда вы запускаете gatsby develop или gatsby build. Это нелогично, как работает Гэтсби, но прочтите сами:

Gatsby использует GraphQL во время сборки, а не для живых сайтов.

Больше информации о процессе сборки gatsby и о том, как на него влияет GraphQL.

Это означает, что вы уже построили свой компонент так, как предполагалось. Во время сборки все ваши карты запрашиваются и сохраняются в памяти. При создании HTML-кода для ваших страниц с вашими карточками для создания вашей страницы используются только карточки с вашим идентификатором. Таким образом, пользователь видит только переданные страницы с отфильтрованными идентификаторами.

Вы можете дважды проверить, действительно ли на вашей странице находятся только карты с идентификатором:

  • run gatsby clean: убедитесь, что старые фрагменты вашей страницы удалены
  • run gatsby build: Создайте свой сайт с нуля
  • Проверьте папку public в корне вашего проекта. Это классическая веб-страница, которую создает Гэтсби. Перейдите на свои страницы со своими карточками, например /public/blog/example-page-with-card. Загляните внутрь HTML-кода страницы: содержит ли она все карточки или только одну с нужными вам идентификаторами?

Решено

Я решил это, добавив используемые данные в контекст страницы, отредактировав файл gatsby-node.js:

  1. Получите mdxAST сообщения, отфильтруйте компоненты, затем отфильтруйте используемые идентификаторы.
  2. Добавьте этот список идентификаторов в контекст страницы.
  3. Переместите запрос, указанный в вопросе выше, в пост-запрос GraphQL. Используйте список идентификаторов, предоставленный контекстом страницы, чтобы отфильтровать данные только по используемым идентификаторам в этом сообщении.
  4. Передайте эти данные как свойство MDXRenderer.
  5. Передайте эти данные в файле .mdx компоненту карточек, например: <Cards data = {props.cards_data} />.
  6. Теперь компонент получал данные без использования StaticQuery.

Это работает, но как-то странно. На мой взгляд, должно быть лучшее, более чистое решение.