20210107のReactに関する記事は3件です。

Create React App(TypeScript)でアプリを起動して Material UI ちょこっと触るまで

概略

React は公式のドキュメントが充実しているので, アプリを初期構築するのも比較的容易かと思いますが, 最近触る機会があったので, せっかくなのでアプリ立ち上げと Material UI 使ってみるまでまとめてみました。

React アプリを作成する

アプリを新規作成して初期起動までです。実施環境の Node.js は 2021/01/07 時点で推奨版の 14.15.4 を利用中です。nodenv とかで入れてます。

Create React App を実行する

公式の Doc を辿ると比較的素直に, 新しい React アプリを作るのページにたどり着きます。
書かれているがままに, create-react-app したいところなのですが, TypeScript を利用する場合はこちらの TypeScript 用のページの内容が大事です。

create-react-app する際に TypeScript の指定をしてあげる感じになります。(以下, my-app の箇所は好きなアプリ用の名前を指定してあげてください)

npx create-react-app my-app --template typescript

公式ページでも以下記載がある通りですが, 使用しているのは np"x" です。

最初の行の npx は打ち間違いではありません — これは npm 5.2 から利用できるパッケージランナーツールです。

npx の利点としては, 今までグローバルにインストールして(npm i -g create-react-app), create(npm create-react-app my-app)してたりしたとしたときに, npx 使うと, グローバルを汚さず(npx 実行時 create-react-app がなければ一時的にインストールされる感じでその後消えるので)良い感じに作業できるところですかね。(細かいところは↑のリンクで)

実行結果前半を拾うとこんな感じです。react-scripts with cra-template-typescript が示す通り TypeScript 用でインストールが走っているかと思います。

% npx create-react-app my-app --template typescript 
npx: 67個のパッケージを2.71秒でインストールしました。

Creating a new React app in /your-path/my-app.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template-typescript...

アプリの起動

create-reactt-app 時の最後の方に, いろいろメッセージがでてますので, それを確認すると,

Success! Created my-app at /your-path/my-app
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd my-app
  npm start

Happy hacking!

作ったアプリが create-react-app を叩いたディレクトリ下にできているのでメッセージにしたがって以下を実行します。

% cd my-app
% npm start

すると http://localhost:3000/ に誘導されてちょっと待つと, 最初の画面が描画されます。
AppTop.png
テスト実行とか, Build とか↑のインストール後のメッセージに書かれているのでご参照くださいという感じです。

Material UI を使う

初期画面だと特にこう見栄えを変えるものもあまりないのですが, Material UI をいれてみます。React と同じく公式のドキュメントが豊富なので公式に従っていきます。

Material UI をいれる

公式の Getting Started を参照し, まず先ほど作ったアプリで Material UI をインストールします。

% cd my-app
% npm install @material-ui/core

package.json の dependencies に @material-ui/core が追加されたかと思います。(ちなみに, 僕のインストール時の Material UI は v4.11.2 でした)
いったんこれで使い始められるので, 公式の Getting Started の Font とかのあたりは必要に応じて読んで取り込んでください。

使ってみる

公式の Usage のサンプルで, Material UI の Button をいれてみます。
と言っても簡単で, 先ほど作ったアプリの App.tsxmy-app/src/App.tsx)に以下内容①・②を追加します。わかりやすさのためかなり雑な位置に Button をいれています。

App.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Button from '@material-ui/core/Button'; // ① 追加

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        {/* ② 追加(以下三行) */}
        <Button variant="contained" color="primary">
          Hello World
        </Button>
      </header>
    </div>
  );
}

export default App;

npm start を継続している状態なら保存すれば http://localhost:3000/ で描画されるかと思います(してなければ npm start ください)
以下な感じで, 良い感じにデザインがあたったボタンが出てくるかと思います。(背景が暗いので影などがわかりづらいですが)
Button.png
ということで使い方ですが, @material-ui/core などから必要な部品を import して, TSX の中で通常の HTML 要素のように書くだけ, という感じです。便利ですね。

Button 以外の使える部品とか指定できる属性とかいろいろな情報は公式デモ公式 API ドキュメントを参照ください。
@material-ui/icons とかもインストールして使うと, ゴミ箱アイコンとか使えておすすめです。

簡単ですがこのあたりで。次はもう少し実践的なものをかければよいなーというところです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Next.jsチュートリアル】Pre-renderingとData Fetchingを基礎からしっかり学ぶ

前書き

筆者がNext.jsを仕事で書くことになったので、1から勉強するためにアウトプット記事を書くことにしました。
基本的にはドキュメントを噛み砕いて、翻訳した記事です。間違っているところなどあれば、ご指摘していただけるとありがたいです?‍♂️

以下、本題です。

Pre-renderingとは...?

事前にHTMLを生成することです。Next.jsではデフォルトで全ページをPre-renderingしてくれています。事前に生成してくれるので、ブラウザの負荷を下げてくれます。また、通常のReactで構築されたページよりもSEO的に有利というメリットもあります。

二つのPre-rendering

Pre-renderingには

  • Static Generation:静的ジェネレーション
  • Server-side Rendering:サーバーサイドレンダリング

の二種類があります。Static Generationはビルドされたタイミングで、Server-side Renderingはアクセス(リクエスト)時にHTMLを構築します。

また、ページごとにStatic GenerationServer-side Renderingを使い分けることもできます。

Static GenerationServer-side Renderingの使いわけ

基本的にはStatic Generationが推奨されています。理由は主に二つ。

  • SEOに強い
  • 表示速度が高速

しかし、Server-side Renderingを使ったほうが良いパターンもあります。いくつものユーザーが情報を更新できるようなページです。例えば

  • SNS
  • グループチャット

みたいな感じです。逆にStatic Generationは下記のような用途に向いています。

  • ECサイト
  • BLOGサイト

などの、基本的に一人のユーザーしか更新できないようなページはStatic Generationが向いていると言えるでしょう。

なので...

更新頻度が低いページ:Static Generation
更新頻度が高いページ:Server-side Rendering

みたいに覚えておくと良いかもですね。

Static Generationで外部データを表示させる

以降から、静的ジェネレーションでHTMLを生成する場合の外部データの扱いについて見ていきます。

Static Generationデータがある時、ない時

  • 外部データがない時:ビルド時にHTMLを読み込む
  • 外部データがある時:ビルド時にAPI(外部データ)からデータを取得→読み込む

APIなどの外部データからデータを取得する場合には、getStaticPropc()を使うようにしてください。

getStaticPropc()とは...?

Next.jsにおいて、外部データを取得するために使います。特徴は

  • pageコンポーネントでしか使えない
  • development環境:リクエスト時に実行
  • production環境:ビルド時に実行される。
  • 非同期処理(async/await)で制御可能

実際にやってみる。

Next.jsアプリのトップレベルにpostsディレクトリを作成し、pre-rendering.mdssg-ssr.mdファイルを追加してください。それぞれのファイルの内容は下記。(...と言っても、チュートリアルコピペですが)

pre-rendering.md
---
title: 'Two Forms of Pre-rendering'
date: '2020-01-01'
---

Next.js has two forms of pre-rendering: **Static Generation** and **Server-side Rendering**. The difference is in **when** it generates the HTML for a page.

- **Static Generation** is the pre-rendering method that generates the HTML at **build time**. The pre-rendered HTML is then _reused_ on each request.
- **Server-side Rendering** is the pre-rendering method that generates the HTML on **each request**.

Importantly, Next.js lets you **choose** which pre-rendering form to use for each page. You can create a "hybrid" Next.js app by using Static Generation for most pages and using Server-side Rendering for others.
ssg-ssr.md
---
title: 'When to Use Static Generation v.s. Server-side Rendering'
date: '2020-01-02'
---

We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.

You can use Static Generation for many types of pages, including:

- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation

You should ask yourself: "Can I pre-render this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation.

On the other hand, Static Generation is **not** a good idea if you cannot pre-render a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request.

In that case, you can use **Server-Side Rendering**. It will be slower, but the pre-rendered page will always be up-to-date. Or you can skip pre-rendering and use client-side JavaScript to populate data.

さらにライブラリを取り込んでください。

npm install gray-matter

トップレベルでlibを作成し、posts.jsを追加してください。内容は下記。(こちらもコピペ)

posts.js
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'

const postsDirectory = path.join(process.cwd(), 'posts')

export function getSortedPostsData() {
  // Get file names under /posts
  const fileNames = fs.readdirSync(postsDirectory)
  const allPostsData = fileNames.map(fileName => {
    // Remove ".md" from file name to get id
    const id = fileName.replace(/\.md$/, '')

    // Read markdown file as string
    const fullPath = path.join(postsDirectory, fileName)
    const fileContents = fs.readFileSync(fullPath, 'utf8')

    // Use gray-matter to parse the post metadata section
    const matterResult = matter(fileContents)

    // Combine the data with the id
    return {
      id,
      ...matterResult.data
    }
  })
  // Sort posts by date
  return allPostsData.sort((a, b) => {
    if (a.date < b.date) {
      return 1
    } else {
      return -1
    }
  })
}

そして、pages/index.jsで下記のようにコードを追加してください。

pages/index.js
import { getSortedPostsData } from '../lib/posts'

export async function getStaticProps() {
  const allPostsData = getSortedPostsData()
  return {
    props: {
      allPostsData
    }
  }
}

export default function Home({ allPostsData }) {
  return (
    <Layout home>
      {/* Keep the existing code here */}

      {/* Add this <section> tag below the existing <section> tag */}
      <section className={`${utilStyles.headingMd} ${utilStyles.padding1px}`}>
        <h2 className={utilStyles.headingLg}>Blog</h2>
        <ul className={utilStyles.list}>
          {allPostsData.map(({ id, date, title }) => (
            <li className={utilStyles.listItem} key={id}>
              {title}
              <br />
              {id}
              <br />
              {date}
            </li>
          ))}
        </ul>
      </section>
    </Layout>
  )
}

HomeコンポーネントにallPostsDataを渡しています。このallPostsDataがブログデータということになります。

概要としては、

  • getStaticProps()内で返すデータを変数(or定数)などに宣言。
  • ここではコンポーネントのpropsとして渡すため、キー名propsreturnしています。
  • 渡ってきたデータ(allPostsData)を使って、画面表示をしています。

というような感じです。

外部データを使って、表示させる場合にはgetStaticPropc()を使うようにしましょう。

Server-side RenderingData Fetching

もし、リクエストごとにデータを取ってくるとしたらServer-side Renderingを使うべきです。その場合、getServerSideProps()を使って、データの取得をしてください。

getServerSideProps()を使うことで、ビルド時ではなく、ユーザーのリクエスト毎にデータを取得することができます。

以上です。お疲れ様でした?‍♂️

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React+Firebaseでオンラインストレージ型成長記録WEBアプリを作った。

初めまして、駆け出しエンジニアのじゃむぱんです。
私は2020年の3月程から、フロントエンドエンジニアへのキャリア就職を目指して
今日に至るまで勉強してまいりました。
今回は私の一つ目の成果物を皆さんに発表し、何か一つアイデア等持ち帰って頂けたら
うれしい限りです。

成果物

無題.png
https://guroun-b67f4.web.app/

サイト名:ぐろうん
制作期間:約2週間
フリー画像引用元:
https://piclike.net/
https://icon-icons.com/ja/
https://icooon-mono.com/
http://design-ec.com/?page_id=463

特徴

この「ぐろうん」の特徴は一日毎の成長記録ということです。
栽培、筋トレ、赤ちゃんの成長等種類問わず日単位の成長管理をすることができます。
無題2.png
編集ボタンから画像、コメントを編集することができ、その更新日も追記されます。

なぜ作ったのか

冒頭にも書いてある通り、私はフロントエンドエンジニアとしてキャリア就職したいため
日々、UdemyやProgateを活用し勉強してきました。
しかし、インプットだけしていても実践的な技術を学ぶことはできないため何か一つ成果物を作ることを決めました。
そして、実際に作るものを考え以下の条件を作りました

  • React+Firebase使用する(学んだ技術を使う)
  • ログイン機能を使用する
  • 筋トレのモチベーションを高めたい(個人的理由)
  • 車輪の再発明を極力回避したい

これらの条件を複合的に考えた時、「ランダムに力強い音楽が流れるアプリ」も考えましたが
これはYoutubeで出来てしまうため考え直し、「毎日の成長を記録するアプリ」を作ることに決めました。このような機能を持つアプリは探せばあると思います。
ですが「ランダムに力強い音楽が流れるアプリ」よりは明らかに少数派で車輪の再発明感が少なく、競争相手が少ないためより多くの人が使ってくれるかもしれないと思いこちらを選びました。
いずれ、ポートフォリオにも組み込んでいきたいと考えています。

使用した技術

  • TypeScript(React Hooks)
  • Redux-toolkit
  • Firebase
  • Material UI

Reactライブラリでは、react-modalを使用し、データ追加画面や、表示画面等あらゆる
状況で使用しました。
FirebaseはAuthentication、firestore、cloud storage、hostingを使用しました。

IDE

VScodeで全て書きました。
以前はAtomを使用していましたが、VScodeの自動補完、多数のライブラリ等機能性の高さに心を奪われ半年ほど前にこちらにシフトしました。

使用したVScodeライブラリ

  • Prettier - Code formatter
  • ESlint
  • ES7 React/Redux/GraphQL/React-Native snippets

他にも使用しているライブラリがあるかもしれませんが、主に活躍したのは上三つです。
Prettierはインデントを自動で行い、ESlintは構文ミスをチェックし、snippetsはReactの基本の型を簡単に作り上げるライブラリです。
どれも有用ですのでまだ使っていない方いましたら是非インストールおすすめしてます。

環境はCreate-React-App

NextjsでもGatsbyでもなくCreate-React-Appです。
私はこのアプリを作り始める前、「Nextjsで書こう。」と思い
こちらの記事(https://qiita.com/thesugar/items/01896c1faa8241e6b1bc)
で二日ほどかけてNextjsの基本構文や、SSR、SSGとは何か等を学習させていただきました。
勉強していくうちに、SSR、SSGの圧倒的早さに感動しました。
そして学習を終えて、私は結局Create-React-Appで書くことに決めました。
その理由は以下です。

  • 大規模なアプリを作るわけではないため速度に大きな差は出ないと判断したから
  • SPAはSEOに弱いためブログに向いていないといわれるが、そもそもブログではないのであまり影響がないと感じたから
  • どんどん技術を詰め込もうとすると、より多くのエラーが発生し挫折の原因に繋がるから

SSRやSSGは早くてSEOに強いですが、前述のとおり大規模なアプリを作るわけではなく速度に大きな差は出ないであろうと判断し、且つブログ等のようなSEOにとても大きく左右される種類ではないためSPAで十分であると判断しました。
そして何より、私はCreate-React-Appを使用した学習しかやってきませんでした。
なので、いきなり数日でSSRをインプットし成果物として活用するのはあまりに時期尚早であると判断しCreate-React-Appを環境として選択しました。

TypeScript大変

言語はTypeScriptを選定しました。理由としましては以下です

  • バグが見つけやすい
  • JavaScriptだけではなく、TypeScriptに対する需要が高まっていると転職サイトを見て思った

しかし、TypeScriptはそんな素晴らしいメリットがある一方で型の種類が多すぎると感じました。
尤も、厳格な型付けはバグを防ぎ、チームメイトが読みやすい等メリットはありますが
一人で全ての値に型を付けるとなるとそれはとても大変な作業でした。
特に、Firebase周りの型はよくわからないためQiitaの記事を参考に調べて回りましたが他にもどうすれば型付けすればいいのかわからない値が、書いていく中で多数出てきたため、多くの値に"any"を付けてしまいました。
妥協せず、もっと多くの型を調べるべきでした。
そして、私は設計等のような下準備をせず目の前の機能だけを書き続けていました。
これは失敗でした。コンポーネント毎に同じ値を使っているのに別々に定義してしまい、結果的にパフォーマンスを大きく下げることになりました。
よく使う値はRedux-Toolkitに定義し、それを一つ一つ型定義するのではなく別ファイルにinterfaceをexportした形で定義しそれをすべてのファイルで使うようにすればいいと今になって思いました。
しかし、TypeScriptでしっかり書き上げた自分を今日は褒めようと思います。

Redux-ToolkitはReduxより楽。だが大変

状態管理にはRedux-Toolkitを使用しました。理由は見出しの通りで、Reduxより楽だからです。
useReducer+useContextという状態管理の方法もHooksには存在しますが、Redux-Toolkitを学びたいという気持ちからこちらを選定しました。
コマンド
npx create-react-app my-app --template redux-typescript

このコマンドを使って環境構築しました。Create-React-Appが基盤でredux-toolkitがtypescriptで書かれた環境が簡単に出来上がります。
しかし、そんな簡単なredux-toolkitですが私は一つ前の「Typescriptは大変」で書き上げた通り
グローバルで使う値をRedux-Toolkitで管理していなかったので、この技術の本領発揮することができませんでした。
私は、useStateを使ってバケツリレー方式で多くの値を状態管理してしまったが故に、可読性とパフォーマンスを失いました。
もっと先を見据えた状態管理をすべきでした。

Firebaseは割と簡単

Firebaseをバックエンドとして使用しました。
その中のAuthentication、FireStore、Cloud Storage、Hostingを使いました。
Authenticationで新規作成、ログイン処理を行います。
FireStoreにユーザーのデータを管理させ、その中に含まれる写真は一度Cloud Storageに追加してからFireStoreで取り出す形を執っています。
最後にHostingをするだけで後はFirebaseがとやかくやってくれます。
バックエンドに慣れていないフロントエンドの方がアプリを作ろうと思っている場合firebaseはとてもお勧めですね。
バックエンド言語を習得するよりすくない学習コストでリッチなバックエンドができます。

Material UI素晴らしい!

Material UI素晴らしいですね。タグ名を変えて少し設定するだけでリッチでレスポンシブなWEBデザインが出来上がります。
Material UIの日本語教材は比較的少ない傾向にあるため、私はMaterial Uiの公式ドキュメントからフリーのExample(https://material-ui.com/getting-started/templates/)
のGItHubを参考にほぼ全てのページをデザインしました。
こちらもデザインに強くないReactエンジニアの方にとてもお勧めですね。

最後に

最後まで見てくださりありがとうございます。
何か一つアイデアはあったでしょうか?
二回目の投稿ということで語彙力から文章力までまだまだ至らない所が多くあると思います。
私はこれからも勉強を続けてよりわかりやすく有益な情報を皆さんに発信していきたいと思いますので
よければ良い点・悪い点含めてコメント頂けるとありがたいです。
最後まで見てくださりありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む