Gatsby+Netlify+microCMS+Material UI 実装ではまったところ

タイトルの通りですが、Gatsby+Netlify+microCMS+Material UIで個人のwebサイトを作成しました。

www.meru-lotte.com

まだ色々と修正したいところだらけなのですが、現状作ってきた中でハマったところを忘れないうちに書き留めておきます。
願わくば、同じような構成でwebサイトを作っている方のヒントになればと思います。
ということでソースコードも公開しています。
細かいところはおおめに見てください。

github.com

※注意※
細かい設定手順については色々なサイトで丁寧に解説しているので、省略させていただきますmm

WebpackError: ReferenceError: window is not defined

ローカル環境では動くけれど、Netlifyでデプロイしようとするとコケる。

   20 | 
   21 | export default function ContentsContiner(props) {
 > 22 |   const windowHeight = window.innerHeight;
      |                        ^
   23 |   const classes = useStyles(windowHeight);
   24 |   return (
   25 |     <Container fixed className={classes.container} id={props.id}>
 
   WebpackError: ReferenceError: window is not defined
   
   - contentContiner.jsx:22 

こちらは調べるとわりとすぐ出てくるけれど、windowが取得できないらしい。
ので、手取り早く修正するのであればこんな感じでundefinedで一回判定を入れてあげれば解決します。

  if ( typeof window !== 'undefined' ) {
    windowHeight = window.innerHeight;
  }

WebpackError: TypeError: Cannot read property 'allMicrocmsArt' of undefined

こちらも、ローカルではうまく動くけれども、Netlifyにデプロイするとコケるパターン。
allMicrocmsArtはmicroCMSから取得しようとしている要素名です。
各々の環境で別の名称になってくると思います。

エラーが出た時の構成はこんな感じです。

./src/pages
├── about.tsx
├── art.tsx    // 実際にdataを使用するコンポーネント
├── index.js
├── index.tsx  // ここでgraphqlでdata取得
├── skill.tsx
└── top.tsx

index.tsxにかいていたコードはこんな感じです。

const App = ({data}) => {
  const classes = useStyles();
  return (
      <>
        <Header/>
        <Top id="top" />
        <About id="about"/>
        // ↓↓↓↓丸ごとdataを渡している
        <Art data={data} />
        <Skill id ="skill" />
        <Footer/>
        <ScrollTop classes={classes} >
      </>
  )}

export const query = graphql`
query {
  allMicrocmsArt {
    nodes {
      id
      title
      createdAt
      picture {
        url
      }
      thumbnail {
        url
      }
    }
  }
}
`
export default App;

結局のところ、取得するデータがどこで使われるかを適切に判断し、必要なものを必要な場所で必要な分だけ取得してあげる必要があります。(それがgraphqlの良さでもありますしね)
エラー自体は親からもらったdataをそのまま子コンポーネントに渡していたので、型解決ができずに子コンポーネントで落ちると言った状況でした。
今回の場合、親コンポーネントは取得したallMicrocmsArtを全く使用しないため、データは子コンポーネント内で取得されるべきでした。
そして、子コンポーネントで静的なデータとして使用する場合には、useStaticQueryを使用するのが良いようです。

const Art = () => {
  const data = useStaticQuery(
    graphql`
      query {
        allMicrocmsArt {
          nodes {
            id
            title
            createdAt
            picture {
              url
            }
            thumbnail {
              url
            }
          }
        }
      }
    ` 
  )

-- 中略 --

  return (
    <ContentsContiner id='art'>
      <Typography variant="h3" gutterBottom>
        art work.
      </Typography>
      <GridList cellHeight={160} className={classes.gridList} cols={col}>
        // ↓↓↓↓ この辺から
        {data.allMicrocmsArt.nodes.map( node =>
        <GridListTile key={node.id} cols={1}>
            <img 
              src={node.thumbnail.url} 
              alt={node.title} 
              className={classes.thumbnail}
              onClick={() => handleToggle(node.picture)} />
          </GridListTile>
        )}
      </GridList>
    </ContentsContiner>
  );
}

export default Art;

Qeryをコンポーネント内に記述するので少し長くなって読みにくくなるのはちょっといまいちだなぁとは思いますが、
こんな感じでuseStaticQueryで取得した値をconstに入れてあげればデータを取得することができます。

Material UIでCSSアニメーションを設定する

こちらは、以下の記事を参考にしました。ありがとうございます。

qiita.com

こんな感じです。

const useStyles = makeStyles((theme) => ({
  image: {
    animation: '$fadeIn 1 1s linear'
  },
  '@keyframes fadeIn': {
    from: {
      opacity: 0
    },
    to: {
      opacity: 1
    }
  }
}));

本当にメモ程度で恐縮です。
Netlifyちゃんと触ったの初めてだったのですが、設定簡単すぎて拝みました。
それとCMSにmicroCMSを採用した理由ですが、日本製だからというのが10割りです。
困ったときに母国語でドキュメントが整備されているのはこれ以上ないアドバンテージです。
管理画面も見やすくて推せます。

Material UIは今回レイアウトで結構うんうん唸ってたので、一から自分で作っても良かった説はありますが、
Reacのファイル内にCSSを記述する上でuseStylesが見やすくて好きなので、これで良かったのだと思います。

今後もウェブサイトの細かい修正は続いていくので、また何かあればかこうと思います。