- 投稿日:2021-01-14T23:46:51+09:00
ReactでGoogleMapAPIの使い方
はじめに
ReactでGoogleマップを表示させる方法をまとめました。
Reactのライブラリである@react-google-maps/apiを利用します。
GoogleMapのAPIキーは事前に取得及び有効化をお願い致します。参考サイト
こちらの記事を参考にさせていただきました。
https://medium.com/@allynak/how-to-use-google-map-api-in-react-app-edb59f64ac9d
日本語でググってイマイチだった場合は、英語でググるといい記事が見つかることがよくあります。
自分はいつも、How to use "キーワード" in "言語" みたいな感じで検索します。
今回だったら How to use Google Map in Reactで検索しました。導入方法
まずは@react-google-maps/apiを利用できるようにターミナルで準備します。
create-react-appで作成したプロジェクトのディレクトリで、
とりあえず自分はいつも最新バージョンを調べます。$ npm info @react-google-maps/api結果の一部がこちら↓
@react-google-maps/api@2.1.0 | MIT | deps: 4 | versions: 98 React.js Google Maps API integration https://react-google-maps-api-docs.netlify.app/今現在のの最新バージョンは@react-google-maps/api@2.1.0だったのでこれをyarn addします。
$ yarn add @react-google-maps/api@2.1.0一番下にDone in 何秒と出てきたら成功です。
これでこのプロジェクトで@react-google-maps/apiのライブラリが利用できるようになりました。Mapの表示
まずはライブラリから必要なものをImportします。
Map.jsimport React from 'react'; import { GoogleMap, LoadScript } from '@react-google-maps/api';中はアロー関数を使って書きました。
Map.jsconst Map = () => { const mapStyles = { height: "100%", width: "100%" }; const defaultCenter = { lat: 41.3851, lng: 2.1734 } return ( <LoadScript googleMapsApiKey='YOUR_API_KEY'> <GoogleMap mapContainerStyle={mapStyles} zoom={13} center={defaultCenter} /> </LoadScript> ) }mapStylesの中のstyleを変えれば地図の形が変わりますし、defaultCenterのlatとlng(緯度と経度)を変えれば初期表示の中心地を変えれます。
YOUR_API_KEYをご自身のGoogleMapのAPIキーに変更してください。
ここまででMapが表示されたかと思います。
Markerの表示
次に指定した場所にピンを立ててみようと思います。
ピンもライブラリからimportが必要です。
先ほどのimportにMarkerも追加します。Map.jsimport { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';そしてピンを立てる場所を指定します。
今回は2箇所を配列にいれてあげます。Map.jsconst locations = [ { name: "Location 1", location: { lat: 41.3954, lng: 2.162 }, }, { name: "Location 2", location: { lat: 41.3917, lng: 2.1649 }, }, ];最後にGoogleMapの間にMarker情報入れてあげます。
map関数を使用して、上で指定したlocationsの情報を一つずつitemに入れていくイメージです。Map.js<GoogleMap mapContainerStyle={mapStyles} zoom={13} center={defaultCenter}> { locations.map(item => { return ( <Marker key={item.name} position={item.location} /> ) }) } </GoogleMap>infoWindowの表示
最後にinfoWindowを表示させたいと思います。
またライブラリからimport
今回はInfoWindowだけでなくuseStateも使うので併せてimportします。Map.jsimport React, { useState } from 'react'; import { GoogleMap, LoadScript, Marker, InfoWindow } from '@react-google-maps/api';ピンをクリックしたら表示されるようにしたいので、関数を作っておきます。
Map.jsconst [selected, setSelected] = useState({}); const onSelect = item => { setSelected(item); }クリックするとonSelectが実行され、selectedの配列にitemの情報が入ります。
Map.js{ locations.map(item => { return ( <Marker key={item.name} position={item.location} onClick={() => onSelect(item)} /> ) }) } { selected.location && ( <InfoWindow position={selected.location} clickable={true} onCloseClick={() => setSelected({})} > <p>{selected.name}</p> </InfoWindow> ) }終わりに
GoogleMapの使い方は他にもあるかと思いますが、個人的にはライブラリを使用するのが楽かなと思いました。
もしかしたらライブラリを使用することによって制限されるものがあるかもしれませんので、発見したらまた共有させていただこうと思います。
最後まで読んでいただきありがとうございました。
- 投稿日:2021-01-14T23:36:13+09:00
【Tailwind + React】NavLinkを使ってactiveクラスをスタイリングする方法
NavLink利用時の問題点
・通常時のテキストカラーは黒
・アクティブ時はテキストカラーが白、背景色は黒以上のようにスタイリングを行いたい場合、
activeClassName
を使用てもスタイリングが上書きされない。react.jsx<NavLink className={`inline-block px-4 py-2 rounded-full font-semibold text-sm text-black`} activeClassName={`bg-black text-white`} to={`/blogs/${user.uid}`} > ブログ </NavLink>解決方法: @applyを使用してスタイリングを行う
Tailwind導入の際に作成した
index.css
内で@applyを作成してスタイリングをあてる。index.css/* ./src/index.css */ @tailwind base; @tailwind components; @tailwind utilities; a.active { @apply bg-black text-white; }以上のように
aタグ
のclass内にactiveが付与される。
a.active
と指定することで、activeが付与された際のスタイリングを当てることが可能。また、その際は
NavLink
のactiveClassName
は使用しないので削除してOK。react.jsx// 通常時(inactive)のスタイリングがベースとなる <NavLink className={`inline-block px-4 py-2 rounded-full font-semibold text-sm text-black`} to={`/blogs/${user.uid}`} > ブログ </NavLink>
参考リンク
Conflicting className precedence rules #1010
Tailwindドキュメントのindex.css
- 投稿日:2021-01-14T23:32:08+09:00
【React】メルカリ出品に便利な説明文メーカーを作ってみた
はじめまして!
Djangoでウェブアプリらしきもの作ったり、RESTAPI作ったりしていたのですが、
フロントエンドもやろうと思い、Reactを前にはじめました(DjangoのAPIとつなげたアプリも自作中です。後に記事にします。)作ったきっかけは、
- メルカリで本を売るときにトラブルを起こさない
- かんたんに必要な情報を提供する
- ツールとして少なくとも自分が使う
これだけです。
リンク↓(後にドメインはとります。)
https://github.com/cota-eng/mertool
https://xenodochial-shannon-305440.netlify.app/使用技術など
- React(Hooks,useState,useEffect,useRef etc)
- TypeScript
- Netlify
- Material ui
です。どうせならTypescriptも使おうという感じです。
要件定義らしきこと
必要なことをまとめました。
- 新刊購入したものかどうか
- 表紙の傷の程度
- 折れ・書き込みの有無と種類
- タバコ・ペットなどアレルギーを引き起こすものの有無
これらさえ伝われば、メルカリで本を売るときのトラブルはなくなるはずです。(あとは写真次第)
設計らしきこと
一応、親子のコンポーネントだけ作りました。
App.tsxに7つのコンポーネントを紐付け、propsで生成する文章のみ管理しました。
作るときに迷ったこと
TypeScriptでの型定義において、propsでも型定義をするのが斬新で、最初は迷いました。
また、イベントごとに型が決まっているのも、ググりながらなんとか解決できました。
ちょこちょこやって、合計4日くらいかかったように思います。
実装したいことをコードに落とし込む
新刊購入したものかどうかを扱うのはシンプルでした。例えば以下のような感じ。
const handleIsNew = () => { setIsNew(!isNew); }; const [isNew, setIsNew] = useState<boolean>(true); const isNewText: string = isNew ? "新品で購入した本です。\n\n" : "新品で購入したものではありません。\n\n"; useEffect(() => { props.setIsNewText(isNewText); }, [isNewText, props]);しかし、ペットの種類を選び、それを文章として親要素に渡す方法について迷いがありました。
正直、最適なコードではないですが、とりあえず完成させたかったのでゴリ押ししました。
ペットの有無を選択させるのは、
- ペットがいない
- 犬がいる
- 猫がいる
- その他の動物
の4つのcheckboxで、その条件は、
- ペットがいないを選択したときはほかをdisabledに。
- ペットは複数選択可能
- その他の動物はinputでstateで管理
という感じで、以下のようになりました。主要なstateやeffectだけ載せます。
const [isPet, setIsPet] = useState<boolean>(true); const [isDog, setIsDog] = useState<boolean>(false); const [isCat, setIsCat] = useState<boolean>(false); const [isOthers, setIsOthers] = useState<boolean>(false); const [otherPet, setOtherPet] = useState<string>(""); const classes = useStyles(); useEffect(() => { if (!isDog && !isCat && !isOthers) { props.setIsPetText("ペットは飼っていません。\n\n"); } else if (!isPet && isDog && !isCat && !isOthers) { props.setIsPetText("犬を飼っています。\n\n"); } else if (!isPet && !isDog && isCat && !isOthers) { props.setIsPetText("猫を飼っています。\n\n"); } else if (!isPet && !isDog && !isCat && isOthers) { props.setIsPetText(`${otherPet}を飼っています。\n\n`); } else if (!isPet && isDog && isCat && !isOthers) { props.setIsPetText("犬と猫を飼っています。\n\n"); } else if (!isPet && isDog && !isCat && isOthers) { props.setIsPetText(`犬と${otherPet}を飼っています。\n\n`); } else if (!isPet && !isDog && isCat && isOthers) { props.setIsPetText(`猫と${otherPet}を飼っています。\n\n`); } else if (!isPet && isDog && isCat && isOthers) { props.setIsPetText(`犬と猫と${otherPet}を飼っています。\n\n`); } }, [isPet, isDog, isCat, otherPet, isOthers, props]); useEffect(() => { if (isPet === true) { setIsDog(false); setIsCat(false); setIsOthers(false); } else if (isDog === true || isCat === true || isOthers === true) { setIsPet(false); } }, [isPet, isDog, isCat, isOthers]); const otherPetHandler = (e: React.ChangeEvent<HTMLInputElement>) => { e.preventDefault(); setOtherPet(e.target.value); };超無理やりですが、できます。
chromeのconsoleをみる
また、chromeのdevtoolでconsoleから、時間が結構かかってるよ~という警告がたまに発生していたのですが、それはすべて解決できました。
例えば、
- 文章生成するのは、ボタンを押したときだけにする
- ↑最初はuseEffectで常に監視していたため関数が無駄に動作していたことが発覚した
他にも、
- なるべく描画させる回数をへらすことを意識した。
- ↑三項演算を多用していたときに時間がかかっていた。
などなど、他にも数え切れないですがたくさん学びがありました。
参考資料
- 投稿日:2021-01-14T22:34:52+09:00
【基礎の基礎編】React + Express + GraphQLでHello World!
はじめに
この記事は、GraphQLの基礎の基礎として、サーバーサイドとクライアントサイドを最低限実装し、GraphQLで接続する機能を実装しています。データの更新や、DB接続してデータを取得したりなどは行っていません。GraphQLでクライアントとサーバーの連携の概要を理解していただければと思います。
source
https://github.com/kyokozuka/react-node-express-graphql
GraphQLとは
GraphQLはAPIのための問い合わせ言語です。クエリを実行してデータを呼び出すためのランタイムをさすこともあります。
GraphQLの問い合わせ言語
GraphQLは、データベースに問い合わせるために開発されたSQLの考え方をインターネットに適用したものです。単一のGraphQLのクエリを使い、関連するデータをまとめて取得できます。また、データを変更したり削除したりすることもできます。SQLとGraphQLは問い合わせ言語という点で共通しています。
ただ、どちらも問い合わせ言語ではあるものの、GraphQLとSQLは全く異なるものです。
- SQLのクエリはデータベースに対して実行される(データベースのための問い合わせ言語)
- GraphQLのクエリはAPIに対して実行される(インターネットのための問い合わせ言語)
構文
- SQL: SELECT, GraphQL: Query
- SQL: INSERT/UPDATE/DELETE, GraphQL: Mutation
GraphQLはインターネットのための問い合わせ言語なので、ソケット通信を使ってデータの変更を監視するためのコマンドも用意されている。そのコマンドを"Subscription"と呼びます。
GraphQLサーバーの実装
まず、サーバーサイドとして、簡単な(Hello Worldを表示する)APIを作成してみましょう。
今回はApollo ServerはOSSで、非常にシンプルにセットアップできる上、本番環境に投入できる水準の機能を多く提供しています。
代表的な機能としては、サブスクリプションのサポート、ファイルのアップロード、既存のサービスのAPIからデータを取得する機能、クラウドサービスのApollo Engineがあります。環境構築
ディレクトリ構成
myappServer/ ├ node_modules ├ src ├ resolbers ├ index.js └ Query.js ├ index.js └ typeDefs.graphql └ package.json$ npm init -y // 初期化処理 $ npm install express apollo-server-express graphql-playground-middleware-express // モジュールのインストールプログラム
index.jsconst express = require("express"); const { ApolloServer } = require('apollo-server-express'); const { readFileSync } = require('fs'); const resolvers = require('./resolvers'); const typeDefs = readFileSync('./src/typeDefs.graphql', 'utf-8'); const app = express(); const server = new ApolloServer({typeDefs, resolvers}); server.applyMiddleware({ app }) app.get('/', (req, res) => res.end(`Welcome to the PhotoShare API`)) app.listen({ port: 4000 }, () => console.log(`GraphQL Server runnning @ http://localhost:4000{server.graphqlPath}`))typeDefs.graphqltype Query { helloWorld: String! }resolvers/index.jsconst Query = require('./Query'); const resolvers = { Query } module.exports = resolversresolvers/Query.jsmodule.exports = { helloWorld: () => 'Hello World' }サーバーの起動
$ cd myappServer $ node src/index.js >>> GraphQL Server runnning @ http://localhost:4000{server.graphqlPath}GraphQLクライアントの実装
次に、先ほど作成したGraphQLサーバーにクライアントからアクセスしてみましょう。
reactプロジェクトの作成
$ create-react-app myappClientインストール
$ npm install graphql graphql-request
- graphql-request
GraphQLオペレーションをAPIに送信するために利用できるフレームワークがいくつか存在します。その中で有名な"graphql-request"を使用します。これはfetchリクエストをPromiseでラップして、GraphQLサーバーへのリクエストを送信します。また、リクエストの構築とデータのパースに関する細かい処理を引き受けます。
プログラム
作成されたApp.jsを下記のように書き換えてください。
App.jsimport { useState } from 'react'; import './App.css'; import { request } from 'graphql-request' const url = 'http://localhost:4000/graphql' const query = ` query helloWorld { helloWorld } ` function App() { const [hello, setHello] = useState(''); const graphQL = async () => { const result = await request(url, query) setHello(result.helloWorld) } return ( <div className="App"> <button onClick={graphQL}>Click</button> <div>{hello}</div> </div> ); } export default App;request()でurlとqueryを引数として受け取ってサーバーへのリクエストを構築して、結果のデータを返します。ここでレスポンスされるデータは期待した通りのJSONデータ { "helloWorld": "Hello World" } がレスポンスされます。
サーバーの起動
$ cd myappClient $ npm startサーバーが起動したら、ブラウザが立ち上がり、「click」ボタンをクリックすると「Hello World!」と表示されるはずです。
- 投稿日:2021-01-14T22:23:59+09:00
React使う際の始動手順
この記事はZennに書いてましたが、難易度的にはQiita向けっぽく思えてきたため、こっちにもも同じもの投稿してちょっと反応見させてもらいます
やるときいつも「あーなんだっけ」となるので、後で見返したりうっかり忘れたりした時のためにまとめておきます
TL;DR
React使ってプロダクト作ったりする際の、サーバ起動あたりのコマンド軽くまとめ
前提条件(環境)
・Windows10
・npm結論だけ
PowerShell開いて以下のコマンド
cd Reactプロダクト置いてるディレクトリ npm startこれを実行することで、
http://localhost:3000/
(環境により違うかも)で作ったページが見れる詳細な過程
Windows PowerShellを起動
コマンド叩いて実行する必要があるので、Windows環境ゆえWindows PowerShellを起動する必要があります
(Macだったらコマンドプロンプト、また使用するIDEによってはIDE上でできることも)
なので、検索欄なりスタートメニューなりからWindows PowerShellを起動します対象のディレクトリに移動
起動コマンドについては、
create-react-app プロダクト名
で用意し、作っているReactプロダクトのあるディレクトリで起動する必要があります
そのため、まずcdコマンドで対象のディレクトリ(package.json
のあるところ)に移動しますcd Reactプロダクト置いてるディレクトリ
環境によりますが、PowerShell開いたときのドライブ(たいていCドライブのはず)と別のドライブにディレクトリ置いてあるなら先にドライブ移動の必要もある(自分はDドライブに置いている)ので、その場合は以下の例のようなドライブ移動コマンドを先に打ってドライブを移る過程が必要ですD:試してみたら、ドライブまたぐ場合であってもこれ無しにcdで普通に飛べました
コマンド実行制限の部分解除(場合による)
セキュリティのために、Set-ExecutionPolicyコマンドレットによってスクリプト実行の制限がなされていることがあります(「~ cannot be loaded because running scripts
is disabled on this system.」「このシステムではスクリプトの実行が無効になっているため、~を読み込むことができません」とか出てきたらこれ)
その場合は、以下のコマンド叩いてスクリプト実行の制限を、とりあえずローカルのファイルからは許可するように「RemoteSigned」に設定し、制限を部分解除すれば実行できるようになりますSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Processやり終えたら
Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope Processあたりで戻しておくと安全かもしれません
(状態に関してはGet-ExecutionPolicy
コマンドで確認可能。今回の本題とは外れるので詳しく調べたい場合はググって)サーバ起動
頻出なのでわざわざ言うことは無いと思う以下のコマンドで起動します
npm startyarn使ってる場合はまた変わってきます(
yarn run
とか)ページ確認
ここまでやれば
http://localhost:3000/
(環境により違うかも)で、対象Reactプロダクトのページが標準ブラウザに設定しているブラウザで自動的に開きます
あとは確認しながらReactいじってください素のHTMLなら特に前準備なくてもHTMLファイルをブラウザにドラッグするとかで見れるので、最初の頃はやや面倒に感じました(たまに今でも)
多分自動化する手段とかはありそう
- 投稿日:2021-01-14T22:04:49+09:00
ReactNとHooksによるグローバルな状態管理に関する調査と実験
この記事は実験なので内容の確からしさや有用性はなんともいえません
はじめに
Vueでグローバルステートを管理するライブラリと言えばVuexですが、ReactではReduxというのがあるらしいです。でもReact hooks登場以前の情報が多かったです。そしてパッと見、hooksがあれば、よりシンプルに状態を管理出来るのではないかと思い、色々調べて実験してみました。
ちなみに私はVueしか使ってこなかったReactの初学者です。初学者が王道を避けていきなり考察しているのは、アホっぽいですが、Hooks登場以後の王道パターンは調べてもわからなかった。まだ確立していないなら、どこかの誰かの役には立つかもしれない。
調べたこと
私が調べた時系列順です
Reduxについて
https://qiita.com/daijinload/items/c7015b1117c5beb7e49f
最初にこれを読んだためReduxやる気がなくなってしまったのですが、納得感のある記事(DBデータの二重管理はすべきでないとか)。ここでクラス+シングルトンというパターンに触れられていました。
シングルトンについて
https://qiita.com/NeGI1009/items/f8b17d856a4b15b1ecbc
JSでシングルトンとか考えた事なかったですが、上記の例に添えばとても簡単に実装出来ます。どこでimportしても同一のインスタンスが得られるので、まさにグローバルステートです。これを関心単位でクラス分けすれば、ライブラリを用いずとも見通しのよいステート管理が出来るのでは。
hooksについて
https://ja.reactjs.org/docs/hooks-reference.html#usecontext
useContextを用いれば、ツリーの子コンポーネントのスコープでグローバルな状態管理が出来るそう、ですがコードの見た目があんまり好きじゃなかったです。と思いきや、このAPIを用いたカスタムフックを提供するライブラリ「ReactN」があるらしい。
ReactNについて
https://qiita.com/tuttieee/items/e5b2725b3e58cae9ddd6
https://github.com/CharlesStover/reactn#function-components-1ドキュメントのとおり、Function Componentに対応し
useGlobal
というカスタムフックを提供しています。その前にreact-hooks-global-stateというライブラリもチェックしました、ReactNと似たような事が出来ますがこちらは"フラットな"Objectのみを管理可能でした(1階層のObjectという意味)。ReactNはクラスインスタンスを突っ込んでも問題ありません。実験してみた
上記の調査から、
- ReactNによるグローバルステート管理
- データストアクラスのシングルトン
を試してみる
データストアクラス
/src/store/index.tsexport class DataStore { private val1: number; private val2: number; constructor() { this.val1 = 100; this.val2 = 1000; } add1(x: number) { this.val1 += x; return this; } add2(x: number) { this.val2 += x; return this; } get1() { return this.val1; } get2() { return this.val2; } } // インスタンスをexport export const dataStore = new DataStore();メンバ変数をprivateにする事でgetter,setterの使用を強制する
ReactNの環境構築
インストール
npm install reactn
手動で型定義
管理すべき状態(=State)の型を定義しておく
// /src/global.d.ts import 'reactn'; import { DataStore } from './store'; declare module 'reactn/default' { export interface State { state1: DataStore; state2: number; } }関数コンポーネント側でimport
ReactNはReact自体をラップしますので、以下のようにimportします。
import React, { useEffect, useRef, useState } from 'react';なら、以下に書き換える
import React, { useEffect, useRef, useState, useGlobal } from 'reactn';ReactのAPIはそのまま使えて、useGlobalやsetGlobalといった関数が追加されています。
グローバル変数を定義・初期値をセット
setGlobal()を実行することでグローバル変数を定義出来ます。ドキュメントによれば、ReactDom.render()前にすべきとの事ですので、プロジェクトのエントリーポイントで一度だけsetGlobal()するのがよいでしょう。
https://github.com/CharlesStover/reactn#initializing-your-stateimport { dataStore } from './store'; const state = { state1: dataStore, state2: 999, }; setGlobal(state); ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root'), );グローバル変数を取得・更新
useGlobal()を用います。デフォルトのhooksであるuseState()と全く同じ使い方です。
// setGlobal()の引数のオブジェクトのkeyで取得する変数を指定出来る // TypeScriptによるコード補完が効く const [state1, setState1] = useGlobal('state1'); const [state2, setState2] = useGlobal('state2'); // return ( <div className="App" onClick={() => { // DataStore //state1.val1 += 5000; //これはできない setState1(state1.add1(10)); // number setState2(state2 + 1); // 999 -> 1000 }} > <span> {state1.get1()} {state2} </span> </div> );シングルトンをsetGlobal()するなら、最低限getter,setterで値を操作するようにしないと、状態管理がエライ事になると思います。
グローバル変数の更新に応じDOMを再レンダリング
ReactNによるグローバル変数周りのDOM再レンダリングは以下の条件で発生します。
- useGlobal()の2つ目の戻り値(例:setHogehoge())が実行された場合に再レンダリングが走る
- その際に再レンダリングされるのは、useGlobal()を実行しているコンポーネントのみ
終わりに
- 少なくとも、flatに値を保持するなら、ReactNで良い気がする
- ReactNはflatなオブジェクトだけでなく、クラスやネストしたオブジェクトをグローバルで扱いつつDOMに反映させられるので便利だと思うけど、扱いが難しそう(useGlobalで取得したオブジェクトはconstだけど、メンバ変数は保護されないし…)
以下が解決すればうれしいなぁと妄想
- setGlobal()した値が、下位のコンポーネントでしか参照出来ないようにする(今は親でも取得出来てしまうのでスコープを与えるということ)
- DOMの再レンダリングのタイミング(今は(上記の例で言えば)setState()しないとレンダリングされないが、クラス変数に変更があったら、値を参照している箇所で再レンダリングが走って欲しい、もしかしたらuseEffectで出来たりして)
- 投稿日:2021-01-14T21:14:54+09:00
jsライブラリの学習を始めてから出てきた横文字いろいろ
DOM(Document Object Model)
HTMLの各タグ(要素)をNodeとみなして、階層構造で表現するモデルに変換することで、HTMLをJavaScript等で扱えるようにした技術。
仮想DOM
実際のDOMを構築する前に、バーチャルなDOMを構築するワンクッションを入れることで、プログラマがDOMを意識ないで済む。
さらに、バーチャルなDOMを構築する際に差分更新する仕組みをとることで画面更新を高速化できる。この仮想DOMを取り入れたJavaScriptフレームワークが、REACTとかVue.js
バンドル
多くの React アプリケーションは、Webpackなどのツールを使ってファイルを「バンドル」している。バンドルはインポートされたファイルをたどって、それらを 1 つのファイルにまとめるプロセスです。このバンドルされたファイルを Web ページ内に置くことによって、アプリ全体を一度に読み込むことができます。
↓
コーディングを行う際に、複数のファイルを1つのファイルに出力すること。コードをまとめるみたいな意味。コード分割
必要なコードだけを読み込み、初期ロードの際に読む込むコード量を削減する。つまり高速。
例えば、トップページを呼び出すと、トップページに必要なjsだけが読み込まれる。
トップページに必要なコードが読み込まれた後に、Linkコンポーネントによってリンク先のページのコードをバックグラウンドでプリフェッチングする。
リンクを押す頃には読み込みが終わっているため、ページ遷移も高速。すごい。。。プリフェッチング
コードを先に読み込んでおくこと。
preがあらかじめみたいな意味。コンポーネント
何かの部品。
Reactでは、見た目を機能ごとにコンポーネント化して、コンポーネントを組み合わせることでWebサイトの見た目を作る。CSS-in-JS
JSの中でCSSを書ける。
styled-jsxは、CSS-in-JSのライブラリ。
1ファイルで書ける。
react.componentとして提供されてる分、楽。
例)styled-components、 emotion、 MATERIAL-UICSS Modules
CSS-in-JSとは別に、CSSを生で書くこともできる。
CSSファイルをReactコンポーネントの中でインポートすることができる。
CSS Modulesは自動的に一意のクラス名を生成するため、クラス名の衝突が起こらない。(CSS-in-JSも)
Next.jsのコード分割は、CSSモジュールに対しても機能する。
例)テイルウィンド、
チュートリアルした感じ、CSS Modulesの方が地道だけど分かりやすそう。
どっちを使うにしろ、アプリごとでどっちかに統一した方が良さそう。
Tailwindは、CSSModulesではなくグローバルに読み込んでpurgecss (使われてない CSS を削除するものです)と合わせて使うのが基本。なのでパフォーマンスいい。プリレンダリング
レンダリング:何らかのデータをもとにして表示内容を作る。HTMLをもとにページを生成する。みたいな
Next.js はすべてのページをHTMLでプリレンダリングする。DOMにするということ??
まず各ページのHTMLを生成する。その後、そのページに必要な最小限のJSを関連付ける。(このプロセスはハイドレーションと呼ばれる)。ビルド
ソースコードを実際に動くプログラムに変換するコンピュータ上で実行されるプロセス。
静的生成(SSG)
ISR:SSGを何秒間隔でするみたいな機能。
サーバサイドレンダリング(SSR)
リアルタイム性が求められるアプリはこっちが向いてる。
クライアントサイドレンダリング(CSR)
プリレンダリングは行わずに、クライアント側の JavaScript を使用してデータを埋め込むこと。?
フェッチ
データベースなど外部データの取得
- 投稿日:2021-01-14T17:13:06+09:00
Netlifyへ新規Gatsbyサイトをデプロイする
最近Gatsbyをさわることがあって他にもいろいろ試したいので、"新規サイトをローカルで生成してNetlifyへのデプロイ"までを忘れないようにメモしました。
NetlifyとGatsby
Netlify
Netlifyは静的サイトのホスティングサービスです。
- 無料で使い始めることができる
- 結びついているgitリポジトリにpushすると自動で最新バージョンのサイトをビルドできる
という特徴があり、プロトタイピングに便利です。
Gatsby.js
静的サイトジェネレータの1つ。こちらがとても詳しいです。
環境など
- macOS Catalina
- Node.js v12.18.3
- GitHubでリポジトリを作成してローカルからpushできる状態にある
ローカル開発用にセットアップ
バージョン2.27.0で搭載されたインストール方法を使ってみます。
npm init gatsbyいくつかの質問が続くので答えていきます。
#名前を聞かれる デフォルト名"My Gatsby Site"でよければそのままEnter What would you like to call your site? ✔ · My Gatsby Site #以下の3つの質問はそのままEnterで進む What would you like to name the folder where your site will be created? ✔ node/ my-gatsby-site ✔ Will you be using a CMS? · No (or I'll add it later) ✔ Would you like to install a styling system? · No (or I'll add it later) #この質問は複数選択 なにも選択しないので↓キーでDoneまで進めてEnter ? Would you like to install additional features with other plugins? (Multiple choice) Use arrow keys to move, enter to select, and choose "Done" to confirm your choices ◯ Add the Google Analytics tracking script ◯ Add responsive images ◯ Add page meta tags with React Helmet ◯ Add an automatic sitemap ◯ Enable offline functionality ◯ Generate a manifest file ◯ Add Markdown support (without MDX) ◯ Add Markdown and MDX support ───── ❯ Done Thanks! Here's what we'll now do: ? Create a new Gatsby site in the folder my-gatsby-site ? Shall we do this? (Y/n) › Yes #最後にこのプロンプトで止まるのでそのままEnterうまくいくと以下のメッセージがでます。
? Your new Gatsby site My Gatsby Site has been successfully createdサイト確認(ローカル)
npmも使えますが今回はyarnを使ってます。
開発モードで確認
#上記設定で作成されたディレクトリへ入る (上記デフォルトのままだとmy-gatsby-site) cd my-gatsby-site #開発モードでサイトのサーバ起動 yarn developメッセージが多く出ると思いますが、通常
You can now view my-gatsby-site in the browser. ⠀ http://localhost:8000/
が含まれていると思います。
http://localhost:8000/
へアクセスすると現状のサイトを確認できます。サーバの終了は
control+C
です。本番用サイトを生成して確認
#本番用サイトを生成 yarn build #生成された本番サイトをローカルサーバで起動 yarn serve開発内容によってはビルド段階でエラーがでることがあるので、デプロイ前に上記コマンドで一度ローカル確認したほうがいいです。
問題なければ以下の出力がでてアクセスできるようになります。You can now view my-gatsby-site in the browser. ⠀ http://localhost:9000/
これもサーバの終了は
control+C
です。デプロイ
Githubにプッシュ
githubに新規リポジトリを作ったあと、ローカルからプッシュします。
Netlify
アカウントがない場合は sign up からアカウント作成できます。自分はGitHubアカウント認証で作りました。
ログイン直後のホーム画面にある New site from Git をクリック
Create a new site の画面になるのでGitHubのボタンをクリック
GitHubリポジトリの詳細設定に移ります。先程作成したリポジトリが所属するGitHubアカウントをクリック。
GitHubへのnetlifyプラグインのインストール設定になります。Only select repositoriesを選択 -> select repositories で先程作成したリポジトリを選択。netlifyがGitHubへ接続する際のアクセス設定について説明されているので、これで問題なければInstallをクリック。
もう一度Create a new site の画面になるのでGitHubのボタンをクリック。
先程追加したリポジトリが追加されているはずなのでそれをクリック。
デプロイ設定に移るが、Netlify側で自動設定しているようで通常は下記のようになる。そのまま Deploy Site をクリック。
Site deploy in progressはデプロイ進行中。デプロイが終わると表示がURLに変わってアクセス可能になります。
参考文献
- 投稿日:2021-01-14T11:01:10+09:00
【TypeScript + React Hooks】useReducerでactionの型定義をtypeの値によって変更する
はじめに
TypeScript + React HooksのuseReducerで、オブジェクトの配列のstateを作成したとき、
dispatch関数がtypeの値に応じて必要な引数だけを要求するようにしたくなったつまり、reducerの引数であるactionが、
typeの値に対応したpayloadを持つように型定義したい方法
型定義において、typeを
type: string;
ではなく具体値で定義するinterface AddAction { type: 'add', payload: { id: number; a: number; b: string; } }interface RemoveAction { type: 'remove', payload: { id: number; } }定義したそれぞれの型を
|
でつなぐconst reducer = ( state: Array<MyDataType>, action: AddAction | RemoveAction, ) => { if (action.type === 'add') { // addの処理 } else if (action.type === 'remove') { // removeの処理 } }実装例
- オブジェクトの配列であるstateについての実装例
users
:ユーザ情報(id, name, age)を管理するオブジェクトの配列のstate- 新たにユーザ情報を追加する
add
と、idをもとにageを更新するupdateAge
を実装sample.tsximport React, { useReducer } from 'react'; interface User { id: number; name: string; age: number; gender: string; } interface AddAction { type: 'add'; payload: User; } interface UpdateAgeAction { type: 'updateAge'; payload: { id: number; age: number; }; } export const reducer = ( state: Array<User>, action: AddAction | UpdateAgeAction ): Array<User> => { if (action.type === 'add') { // addの処理 } else if (action.type === 'updateAge') { // ageの更新処理 } } const MyComponent: React.FC = () => { const [users, usersDispatch] = useReducer(reducer, []); const addUser = (newUser: User) => { usersDispatch({ type: 'add', payload: newUser, } } const updateAge = (userId: number, newAge: number) => { usersDispatch({ type: 'updateAge', payload: { id: userId, age: newAge, } } } // 以下省略 }