web-dev-qa-db-ja.com

動的画像ソースを備えた再利用可能なギャツビー画像コンポーネント

次のプロジェクトでGatsby-Imageを使用することを考えており、少し遊んでいます。

私はそれを私のテストプロジェクトで動作させるようにしましたが、その後、通常のようにGatsbyのを使用したいというユースケースを思いつきました<img src”image.png”> 鬼ごっこ。したがって、私の質問は、Gatsbyコンポーネントを再利用可能にする方法です。

import React from "react"
import { StaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
function renderImage({ file }) {
  console.log({ file })
  return <Img fluid={file.childImageSharp.fluid} />
}

// Stateless Image component which i guess will recieve src value as a prop?
// Returns a StaticQuery component with query prop and render prop. Query prop has the graphql query to recieve the images and render prop returns a renderImage function which in return, returns a Img component från Gatsby with set attributes.
const Image = () => (
  <StaticQuery
    query={graphql`
      query {
        file(relativePath: { eq: "gatsby-astronaut.png" }) {
          childImageSharp {
            fluid(maxWidth: 300) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    `}
    // render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
    render={renderImage}
  />
)
export default Image

私の最適な使用例は、Gatsby.configファイルで定義されている相対パスに動的なリクエストを行い、各Gatsbyのsrcプロップを組み合わせて、アセットファイル内のすべての画像と一致させてから表示することです。これでさえ可能ですか?

私はドキュメントを読んで、静的クエリは変数をとることができない-ページだけをとります。しかし、画像をページに関連付けたくありません-通常のimgタグのように、このコンポーネントを好きな場所で使用したいと思います。

私が自分を明確にしたことを願っています。ご不明な点がございましたらお問い合わせください。

これは例です: https://codesandbox.io/s/py5n24wk27

事前にありがとう、エリック

15
erikos93

私もこの答えを探してきました。うまくいけば、これはあなたの質問に答えます:

最終的なコード:

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

// Note: You can change "images" to whatever you'd like.

const Image = props => (
  <StaticQuery
    query={graphql`
      query {
        images: allFile {
          edges {
            node {
              relativePath
              name
              childImageSharp {
                fluid(maxWidth: 600) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
          }
        }
      }
    `}
    render={data => {
      const image = data.images.edges.find(n => {
        return n.node.relativePath.includes(props.filename);
      });
      if (!image) {
        return null;
      }

      //const imageSizes = image.node.childImageSharp.sizes; sizes={imageSizes}
      return <Img alt={props.alt} fluid={image.node.childImageSharp.fluid} />;
    }}
  />
);

export default Image;

画像の使用:

import Image from '../components/Image';
<div style={{ maxWidth: `300px` }}>
    <Image alt="Gatsby in Space" filename="gatsby-astronaut.png" />
</div>

説明

StaticQueryは、テンプレートリテラルでの文字列補間をサポートしていないため、実際に小道具を渡すことはできません。代わりに、StaticQueryのRender部分で小道具のチェックを試みて処理します。

注意事項

すべての画像をスキャンしているため、これがコンパイル時間に影響するかどうかは100%わかりません。もしそうなら、私に知らせてください!

更新:このソリューションはすべての画像をスキャンするため、多くの画像がある場合、バンドルサイズは非常に大きくなる可能性があります。

さらなるカスタマイズ

小道具が渡されない場合、プレースホルダー画像を表示するようにコードを調整できます。

代替案

そうは言っても、 これに取り組む別の方法があります ですが、もう少し作業/コードが必要です。

出典

  • この記事 からコードを変更しました。 (この記事は非推奨のコードを使用していたことに注意してください。)
18
RodrigoLeon

@RodrigoLeonは、あなたのアプローチでそれを行うと、バンドルサイズが劇的に増加することに気づきました。特にあなたが50以上の画像を持っていると言うなら。これを使用してすべての画像をループするときはいつでも、コンポーネントファイルにそれらの画像への参照を作成します。そのため、この方法で行うことはお勧めしません。残念ながら、私が収集できる最善の解決策は、画像の個々のjsファイルを書き出すことです。

3
Dawson Walker