Многоразовые компоненты Gatsby с собственным запросом

Возможно ли в настоящее время в Gatsby создавать повторно используемые компоненты, которые имеют собственный запрос graphql? Если нет, то какой в ​​настоящее время является наименее «связанным» способом передачи данных в повторно используемые компоненты? Кажется, я не могу найти никаких примеров, которые это делают, и я ничего не могу найти в документации.

Скажем, например, вы хотите создать компонент облака тегов для блога, который бы отображался на боковой панели всех страниц «сообщений», а также на одной странице «/ tag-cloud». Вы можете использовать как <TagCloud limit={20} /> или <TagCloud tags={uniqueTags} />. Для этого вам нужно будет запросить все ребра, сопоставить / уменьшить каждый массив tags до уникального упорядоченного набора уникальных строк тегов.

Или, скажем, вам нужен компонент «другие продукты» для страницы каталога, исключающей текущий продукт. Здесь у вас может быть <ProductsList exclude={currentProduct} />. Это будет простой отфильтрованный запрос во время сборки.

Единственный способ, которым я могу это сделать, - это либо обезьяно исправить результаты запроса из createPages(), либо передать данные через context в createPage({path, component, context}). Должно ли это произойти в gatsby-node.js? Есть ли другие способы?


person Andrew    schedule 02.10.2017    source источник
comment
Быстрый ответ - это фрагменты github.com/gatsbyjs/gatsby/ Надеюсь, в ближайшее время у меня будет время написать об этом документацию.   -  person Kyle Mathews    schedule 03.10.2017
comment
Спасибо @KyleMathews (и огромное спасибо Гэтсби). Я изучу и обновлю, когда закончу.   -  person Andrew    schedule 03.10.2017
comment
@KyleMathews - до сих пор не замечаю. Фрагменты (в запросах), похоже, получают только одно ребро graphql, которое они расширяют. Я не вижу ни одного примера, который мог бы получить доступ, например, allMarkdownRemark. В качестве другого примера с аватаром, как бы вы отобразили список всех аватаров всех авторов сайта на одной странице сообщения? Или, если я могу создать список в gatsby-node.js, как мне передать его на все страницы?   -  person Andrew    schedule 03.10.2017


Ответы (2)


Я отвечаю на свой вопрос. Если у кого-то есть лучшее решение, отправьте его, и я с радостью его приму.

Мое текущее решение, на которое я ссылался в своем вопросе и которое я считаю неоптимальным, состоит в том, чтобы собрать все данные, необходимые для многократно используемых компонентов верхнего уровня в pages/index.js (или где угодно, где вы используете createPage({path, component, context}), и ввести данные в context. Это делает их доступными для конструктор component через свойство pathContext Имя pathContext заставляет меня думать, что это злоупотребление духом этого объекта, но он выполняет свою работу.

Например, если у вас есть блог, записи которого могут иметь массив тегов, это может быть ваш gatsby-node.js:

const path = require('path');

const getUniqueTags = edges => {
    const set = new Set();

    edges.forEach(edge => edge.node.frontmatter.tags.forEach(tag => set.add(tag)));

    return [...set];
};

exports.createPages = ({ graphql, boundActionCreators }) => resolve(graphql(`
        query AllPagesQuery {
            allMarkdownRemark {
                edges {
                    node {
                        frontmatter {
                            path
                            tags
                        }
                    }
                }
            }
        }
    `)))
    .then(({ errors, data }) => {
        const { createPage } = boundActionCreators;
        const pageTemplate = path.resolve('./src/templates/page.js');

        if (errors) return Promise.reject(errors);

        return data.allMarkdownRemark.edges.forEach(edge => {
            createPage({
                path: edge.node.frontmatter.path,
                component: pageTemplate,
                context: {
                    path: edge.node.frontmatter.path,
                    tags: getUniqueTags(data.allMarkdownRemark.edges)
                }
            });
        });
    })
    .catch(err => console.log(err));

Тогда ваш templates/page.js может получить такой массив уникальных тегов:

const IndexPage = ({ pathContext }) => {
    const { tags } = pathContext.map(tag => <li>{ tag }</li>);

    return <div>{ tags }</div>;
};

export default IndexPage;
person Andrew    schedule 07.10.2017
comment
Я использую тот же метод. Было бы здорово прийти сюда от @KyleMathews, если есть какая-либо опасность с этим методом, или чтобы объяснить, как можно использовать фрагменты для достижения того же результата. - person serby; 19.01.2018
comment
Трудно узнать больше, не видя свою модель данных (или не зная свой исходный плагин), но в идеале вы должны получить все теги из GraphQL напрямую через pageQuery в каждом компоненте страницы. Это показывает общий подход github.com/gatsbyjs/gatsby/blob/master/docs/docs/ - person chmac; 14.02.2018

Вы можете создать запрос фрагмента в ваших макетах / index.js

export const avatarsFragmentQuery = graphql`
  fragment avatars on RootQueryType {
    avatars: allImageSharp {
      edges {
        node {
           id

         }
       }
    }
  }
`

И используйте его на своих страницах:

export const pageQuery = graphql`
  query BlogQuery {
    site {
      siteMetadata {
        title
      }
    }

    ...avatars
  }
`
person shinework    schedule 21.01.2018