- 投稿日:2020-10-11T23:36:25+09:00
Reactで自動整形しようと思った時にハマったこと【VSCode】
はじめに
最近投稿を始めたTutuです。
VSCodeでEsLint、Prettierを使用して自動整形しようと思ったのですが、チュートリアルを読んでもなかなか適用されませんでした。
その時の自分の解決策を備忘録として残しておきます。原因
以下の画像の「JavaScript React」という部分が「JavaScript」になっていたためReactの書き方である、jsx,tsx内で適用されなかっただけだった。
解決策
該当部分をクリックして出てくる部分で下記画像の「Auto Detect」を選択し、「JavaScript React」と入力するだけ
※このままだと選択時のファイルにしか適用されないので、「.js」拡張子全体に適用したい場合は「Configure File Association for '.js'...」を選択後、同様の操作を行う
最後に
同じような現象でハマってしまっている方のために一応今回このような記事を投稿しましたが、初歩的すぎてあまり役に立たないような気がします....w
- 投稿日:2020-10-11T20:35:44+09:00
Reactで作ったポートフォリオを個人的に振り返る(その1. npmモジュール)(のまた2)
前書き
業務でReactを触る機会が出てきそうなので、復習のため、以前作ったポートフォリオを個人的に振り返ります。
ソースコード
https://github.com/momonoki1990/house_work_memo_front
サービス
https://house-work-memo-front.herokuapp.com/home
(Herokuのフリープランで定期モニタリングも解除したので、めちゃ遅いはずです、すみません)前回
Reactで作ったポートフォリオを個人的に振り返る(その1. npmモジュール)(のまた1)
https://qiita.com/momonoki1990/items/a1edd4fa922cd3ed3b14使用したモジュール
package.json"dependencies": { "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", "@types/chart.js": "^2.9.23", "@types/jest": "^24.9.1", "@types/node": "^12.12.50", "@types/react": "^16.9.43", "@types/react-dom": "^16.9.8", "@types/react-redux": "^7.1.9", "@types/react-router-dom": "^5.1.5", "@types/redux-logger": "^3.0.8", "@types/redux-thunk": "^2.1.0", "axios": "^0.19.2", "chart.js": "^2.9.3", "chartjs-plugin-colorschemes": "^0.4.0", "connected-react-router": "^6.8.0", "date-fns": "^2.15.0", "react": "^16.13.1", "react-chartjs-2": "^2.10.0", "react-dom": "^16.13.1", "react-hook-form": "^6.1.0", "react-redux": "^7.2.0", "react-router-dom": "^5.2.0", "react-scripts": "^3.4.3", "redux": "^4.0.5", "redux-devtools": "^3.5.0", "redux-logger": "^3.0.6", "redux-thunk": "^2.3.0", "typescript": "^3.7.5", "typescript-fsa": "^3.0.0", "typescript-fsa-reducers": "^1.2.2" },Redux関連
redux react-redux redux-thunk typescript-fsa typescript-fsa-reducers @types/react-redux @types/redux-thunk redux-devtoolsReduxは、ReactJSが扱うUIのstate(状態)を管理をするためのフレームワークです。Reactではstateの管理するデータフローにFluxを提案していますが、ReduxはFluxの概念を拡張してより扱いやすく設計されています。
Reduxはstateを管理するためのライブラリーなので、React以外にもAngularJSやjQueryなどと併せて使用することもできますが、Reactと使用するのが一番相性がいいです。
Redux入門【ダイジェスト版】10分で理解するReduxの基礎
https://qiita.com/kitagawamac/items/49a1f03445b19cf407b7Reactでは、stateという「状態」、というか個別の値を、コンポーネントごとに設定することができます。
Reduxは、コンポーネントごとのstateとは別に、stateを一元的に保持・管理できる場所だと思っています。
(要は、通常のstateがコンポーネントごとにローカルにstateを設定・参照できるのに対し、Reduxは、stateをグローバルに設定・参照できる)Action
アクション(何が起きたのか)とそれに付随する情報を持つオブジェクト。
ActionをStoreへdispatch(送信)すると、Storeのstateが変更される。stateの変更は必ずActionを経由して行う(理由は後述)。
Reducer
Storeから受け取ったActionとstateに応じて、変更されたstateを返す純粋関数(同じ引数を渡されたら必ず同じ結果を返す関数)。
Store
アプリケーションの全てのstateを保持するオブジェクト。
Redux 入門 〜Reduxの基礎を理解する〜
https://qiita.com/soarflat/items/bd319695d156654bbe86Providerの目的は2つ
1. Reactコンポーネント内でreact-reduxのconnect()関数を使えるようにすること
2. ラップしたコンポーネントにstore情報を渡すこと
ReactとReduxを結ぶパッケージ「react-redux」についてconnectの実装パターンを試す
https://qiita.com/MegaBlackLabel/items/df868e734d199071b883→ちなみに、私のポートフォリオでは、connect使っていません(どうしたんだっけ?)
とりあえず、Providerの役割として、「ラップしたコンポーネントにstore情報を渡す」(要は、Reduxで管理しているstateを使えるようにする)だけ覚えておきます。上記、Redux関連の用語を並べてみましたが、
reduxとreact-redux
reduxとreact-reduxって、どう使い分けるんだっけ?
redux
Redux本体です。react-redux
Reduxは、Reactの一部ではなく、独立したソフトウェアです。そこで、ReactとReduxをシームレスに融合して使うためのパッケージを追加しておきます。
React.js & Next.js超入門(p.192)
https://www.amazon.co.jp/dp/B07X7DHZ9F/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1具体的には、
createStore, combineReducers, applyMiddlewareなど、Reduxのストアを作るための機能や、Dispatch, AnyActionなどの型情報はredux、Provider, useSelector, useDispatchなどの、ReactにReduxのstateやdispatchを渡す機能はreact-redux
と、とりまざっくりと覚えておくことにします。
redux-thunk
なんだっけ、これ。。。
確か、非同期処理を含むアクションをdispatchするのに必要で、createStoreでReduxのストアを作成する際に、applyMiddlewareでミドルウェアとして登録しておく必要があるんじゃなかったっけ。。。Reduxでは基本的に、Action Creatorによって生成されたActionをStoreにディスパッチすることで単純な同期更新を行っています。そこにRedux-Thunkのようなミドルウェアを導入することでStoreの機能を拡張し、非同期ロジックを記述できるようにできます。
通常Action CreatorはActionオブジェクトを返しますが、Redux-Thunkを使用すると「Thunk」という関数を返すことができるようになります。これによってActionのディスパッチを遅らせたり、特定の条件が満たされた場合のみディスパッチできるようになります。
Redux-Thunkで非同期処理ができる仕組みを理解しよう
https://qiita.com/jima-r20/items/7fee2f00dbd1f302e373仕組みはわかってないけど、大体あってた。
今はそれで良しとする。typescript-fsa, typescript-fsa-reducers
これはあれですよね。あれ。なんかreducerとか何かを書くのを、簡単にするんじゃなかったでしたっけ...?
→TypeScriptでアクションクリエーターとレデューサーが簡単に書けるようになるんでした。参考
reduxをtypescriptで使うならこれを使うしかない。(typescript-fsaがすごい)
https://qiita.com/m0a/items/703d64c74e43cb392a64redux-devtools
インストールしておきながら、まったく使っていませんでした。
今後使ってみたいです。参考
Reduxのデバックに必須!Redux DevToolsの使い方
https://harkerhack.com/react-redux-devtools/後書き
一旦ここまでにします。
書こうと思って調べるほど、自分がよくわかってないことがわかりますね。
そのためにも、ゴミ記事でいいと思ってるんですが、それくらいだったら、ブログかなんかでやった方がいいのかな。
- 投稿日:2020-10-11T20:25:16+09:00
Reactの関数コンポーネントでMapbox GL JSを表示するデモ
はじめに
Vueが好きです(告白)
でもReactの方が流行ってるらしいのでキャッチアップしておかなきゃならんという事でcreate-react-appしてみました
とりあえずMapbox GL JSを表示したかったのですが、関数コンポーネントでちゃんと動く例がネット探してもなかったので備忘録兼ねて記事化しておきます関数コンポーネント?
今まで使ってこなかったのであんまりよくわかってないですがクラスより関数の方が良いらしいです(関数型がトレンドという事でしょう)
ネット上で見つかるReact+Mapbox GL JSの例はほとんどクラスコンポーネントだったので、じゃあよりよいという関数コンポーネントでやってみようとしましたが、hooksがどうとか謎用語連発でちょっと困りましたhttps://sparkgeo.com/blog/build-a-react-mapboxgl-component-with-hooks/
参考サイト(でもこれをコピペしても動きません)コード
App.tsximport React, { CSSProperties, useEffect, useRef, useState } from 'react'; import mapboxgl from 'mapbox-gl'; import 'mapbox-gl/dist/mapbox-gl.css'; const styles: CSSProperties = { width: '100vw', height: 'calc(100vh - 80px)', position: 'absolute', }; const App = () => { const [map, setMap] = useState(null); const mapContainer = useRef(null); useEffect(() => { const initializeMap = ({ setMap, mapContainer, }: { setMap: any; mapContainer: any; }) => { const map = new mapboxgl.Map({ container: mapContainer.current, style: 'YOUR_MAPBOX_STYLE_URL', center: [140, 44.0], zoom: 5, }); map.on('load', () => { setMap(map); map.resize(); }); }; if (!map) initializeMap({ setMap, mapContainer }); }, [map]); return <div ref={mapContainer} style={styles} />; }; export default App;メモ
リファレンス読んでないしほぼ語れる事がないのでほとんど推測
- useState()によりコンポーネント内の変数を1箇所で管理する(っぽい、たぶんgetterとsetterを提供してる)
- useRef()でクラス内のhtml的参照を変数で管理する(っぽい)
- CSSProperties、オブジェクト的にCSS書けるの強そう
- 投稿日:2020-10-11T16:25:21+09:00
Reactで作ったポートフォリオを個人的に振り返る(その1. npmモジュール)(のまた1)
前書き
業務でReactを触る機会が出てきそうなので、復習のため、以前作ったポートフォリオを個人的に振り返ります。
ソースコード
https://github.com/momonoki1990/house_work_memo_front
サービス
https://house-work-memo-front.herokuapp.com/home
(Herokuのフリープランで定期モニタリングも解除したので、めちゃ遅いはずです、すみません)ちなみに、定期モニタリングの参考
Herokuの無料dynoをスリープさせないで24時間稼働させる4つの方法
https://casualdevelopers.com/tech-tips/how-to-prevent-idling-of-free-dyno-on-heroku/
→UptimeRobotを使ってました。使用したモジュール
package.json"dependencies": { "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", "@types/chart.js": "^2.9.23", "@types/jest": "^24.9.1", "@types/node": "^12.12.50", "@types/react": "^16.9.43", "@types/react-dom": "^16.9.8", "@types/react-redux": "^7.1.9", "@types/react-router-dom": "^5.1.5", "@types/redux-logger": "^3.0.8", "@types/redux-thunk": "^2.1.0", "axios": "^0.19.2", "chart.js": "^2.9.3", "chartjs-plugin-colorschemes": "^0.4.0", "connected-react-router": "^6.8.0", "date-fns": "^2.15.0", "react": "^16.13.1", "react-chartjs-2": "^2.10.0", "react-dom": "^16.13.1", "react-hook-form": "^6.1.0", "react-redux": "^7.2.0", "react-router-dom": "^5.2.0", "react-scripts": "^3.4.3", "redux": "^4.0.5", "redux-devtools": "^3.5.0", "redux-logger": "^3.0.6", "redux-thunk": "^2.3.0", "typescript": "^3.7.5", "typescript-fsa": "^3.0.0", "typescript-fsa-reducers": "^1.2.2" },順番に解説(というかほとんど忘れているので復習しつつ)
Material UI
Material UIとは?
公式:Material UI
GoogleのMaterialデザインをベースに開発された、UIコンポーネントライブラリです。
お手軽にMaterialデザインを取り入れられることに加えて、コンポーネントの種類が豊富に用意されているため、それらを組み合わせるだけでも見栄えの良いものを作ることができます。
一からコンポーネントを作るのはつらいとか、デザインを考えるのが難しいとか、それらに工数をあまりかけたくないなどの場合にもおすすめです。
React向けのUIコンポーネントライブラリはいろんなものがありますが、その中で人気の高いライブラリでもあります。
React入門 ~Material UI編~
https://qiita.com/h-yoshikawa/items/efa33101b0a02cba7759@material-ui/core
Material UIの基本のモジュール。基本的なコンポーネントが格納されている。
Material UI
https://material-ui.com/@material-ui/icons
SVGアイコンが格納されています。
Material Icons
https://material-ui.com/components/material-icons/こんな感じで使います。
HomePage.tsximport Button from '@material-ui/core/Button'; import DeleteIcon from '@material-ui/icons/Delete'; <Button variant="contained" color="secondary" data-key={work.id} onClick={handleDelete} startIcon={<DeleteIcon />}>削除</Button> : <DeleteIcon color='secondary' />@types/nodeとCreate React AppとReact DOM
@types/node
node.jsの型ファイル。TypeScriptを使うのに必要。
というか、npx create-react-app sample_react_ts_app --typescript
でReactプロジェクトを作成した時点で、デフォルトで入っている。ちなみに、create-react-appはnpmモジュールで、グローバルにインストールして使う。
Reactアプリケーションの雛形がコマンド一発で作れる。参考
Create React Appで環境構築 – React入門
https://www.to-r.net/media/react-tutorial12/npm install -g create-react-app npx create-react-app sample_react_ts_app --typescriptcreate-react-appを使用した場合にデフォルトでインストール済みのモジュール。
package.json"dependencies": { "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "@types/jest": "^24.0.0", "@types/node": "^12.0.0", "@types/react": "^16.9.0", "@types/react-dom": "^16.9.0", "react": "^16.13.1", "react-dom": "^16.13.1", "react-scripts": "3.4.3", "typescript": "~3.7.2" },そういえば、react-domってなんだっけ?
react-dom パッケージには、DOM 固有のメソッドが用意されており、アプリケーションのトップレベルで使用したり、必要に応じて React モデルから外れるための避難ハッチとして使用できます。ほとんどのコンポーネントでは、このモジュールを使用する必要はないはずです。
render()
hydrate()
unmountComponentAtNode()
findDOMNode()
createPortal()
ReactDOM
https://ja.reactjs.org/docs/react-dom.htmlcreate-react-appで作ったプロジェクトのsrc/index.tsxはこんな感じ。
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') );→「renderぐらいでしか使わない」くらいの認識でいることにしよう。。。
ちなみに、reactはReact本体で、型定義に使ったり、Hookとかをimportして使う。
HomePage.tsximport React, { useEffect, MouseEvent } from 'react'; // コンポーネント関数 const HomePage: React.FC = (props: any) => { return ()} // useEffect Hook useEffect(() => { dispatch(defaultHomeAction()); }, []); // 削除ボタンの処理 const handleDelete = (event: MouseEvent<HTMLButtonElement>) => { dispatch(deleteWorkOfHome(event.currentTarget.getAttribute('data-key'))); }後書き
長くなってしまったので、一旦ここで締めます。
そもそも、Reactの仕組み、仮想DOMとかってなんなんだっけ...?
調べてまとめたい。
- 投稿日:2020-10-11T14:11:47+09:00
React学んでみた Hooks API createContext useContext
React
海外で多く扱われているのjsのFW/ライブラリは
React
一強です。
https://note.com/erukiti/n/na654ad7bd9bb
こちらの記事を見ていただけると納得いただけるのではないでしょうか?
自分の目的などと照らし合わせると確実にReactの学習は避けて通れないものになるので
これからキャッチアップを目指していきます。もちろん現場で学ぶのが一番ではあるので
サクッとキャッチアップした後はアルバイトでも入ってみたい気持ちが強いです。Reactの状態管理のベストプラクティス
こちらのサイトに掲載されています。
https://ics.media/entry/200409/現状3つの手法があるようですね。
Hooks APIによる useContext createContext
これらを使うことで状態管理をより楽に実装していきます。
今回のサービスのディレクトリ構成になります。
全て使うわけではありません。rootコンポーネントに全体の状態管理のパラメータを渡します。
App.jsimport React, {createContext, useState, useReducer} from 'react' import ReactDom from 'react-dom' import {BrowserRouter, Route, Switch} from "react-router-dom"; import GlobalNav from "./GlobalNav"; import Home from "./Home"; import Maxims from './maxim/Maxims' import Post from "./Post"; import Edit from "./Edit"; import Setting from './Setting' import SiteContext from "../contexts/SiteContext"; import reducer from '../reducers' export const MaximContext = createContext() const App = () => { const initialState = { maxims: [ { id: 1, maxim: 'バレーは上を向くスポーツだ', who: '鵜飼コーチ', category: 'スポーツ', description: 'ハイキュー白鳥戦', oneWord: '武者震いしました', } ] } const [state, dispatch] = useReducer(reducer, initialState) return ( <BrowserRouter> <GlobalNav/> <Switch> <SiteContext.Provider value={{state, dispatch}}> <Route exact path="/" component={Home}/> <Route exact path="/maxims" component={Maxims}/> <Route exact path="/post" component={Post}/> <Route exact path="/edit" component={Edit}/> <Route exact path="/setting" component={Setting}/> </SiteContext.Provider> </Switch> </BrowserRouter> ) } if (document.getElementById('app')) { ReactDom.render(<App/>, document.getElementById('app')) }以下で全体のstateを渡すためのcontextをimportしてきています。
App.jsimport SiteContext from "../contexts/SiteContext";以下で全体のstateを渡すためのcontextを作成しています。
SiteContext.jsimport { createContext } from 'react' const SiteContext = createContext() export default SiteContext以下で子孫コンポーネントで利用できるように対応しています。
App.js<SiteContext.Provider value={{state, dispatch}}>App.js... <BrowserRouter> <GlobalNav/> <Switch> <SiteContext.Provider value={{state, dispatch}}> <Route exact path="/" component={Home}/> <Route exact path="/maxims" component={Maxims}/> <Route exact path="/post" component={Post}/> <Route exact path="/edit" component={Edit}/> <Route exact path="/setting" component={Setting}/> </SiteContext.Provider> </Switch> </BrowserRouter> ...子コンポーネントで用いる
今回の構成はPOSTコンポーネントで投稿したものを
LIST画面で表示させていくというものになっています。今回はPOST コンポーネントの箇所は省略させていただきます。
今後改めてまとめます。
※Maximというのは名言という意味で利用しています。
以下のMaximsファイルはmaximを複数持っておりそれらをcomponentに渡します。
Maxims.jsximport React, { useContext } from 'react' import SiteContext from "../../contexts/SiteContext"; import Maxim from './maxim' const Maxims = () => { const {state} = useContext(SiteContext); console.log(state.maxims); return ( <div> <h1>List</h1> <div> <img src="" alt=""/> {state.maxims.map((maxim, index) => (<Maxim key={index} maxim={maxim}/>)) } ) })} <div> </div> </div> </div> ) } export default Maxims以下で子コンポーネントに値を渡しています。
maxims.jsx{state.maxims.map((maxim, index) => (<Maxim key={index} maxim={maxim}/>))以下のmaxim.jsxファイルでは
親のmaximsから受け取ったmaximsをそれぞれ表示させています。maxim.jsximport React, {useState, useContext, useReducer} from 'react' const Maxim = ({maxim}) => { return ( <div> <div> <h3>ID</h3> { maxim.id } <h3>名言</h3> { maxim.maxim } <h3>誰が</h3> { maxim.who } <h3>カテゴリ</h3> { maxim.category } <h3>概要</h3> { maxim.description } <h3>一言</h3> { maxim.oneWord } </div> </div> ) } export default Maxim親のmaximsから受け取ったmaximを表示させます。
このような形で親に保存されている値をグローバルに値を用いることができます。
このhooksの状態管理でいいなと思ったのが
渡したい階層にだけ必要な値を渡せるというところですね。順序としては
- createContextで必要な値を格納
- 親にProviderを設置
- 子コンポーネントでuseContextの引数に作ったcontextを渡す。
- 受け取った値を描画などで用いる。
の順になります。
自分でまとめてみるとかなり内容が整理されました。
やはり言語化作業は大事ですね。値の変更(useReducer)に関しては改めて投稿できればと思っています。
これからも学んだことはしっかり言葉にして誰かに伝えられるように発信していきます。
- 投稿日:2020-10-11T11:47:53+09:00
Firebaseを使ってみた 〜第三章 Firestoreからデータを取得する 〜
React Hooksを使いチャットボットアプリを作成しています。
この章ではFirestoreに保存した中から初期データを取得するまでを行います。
第一章 サービスをデプロイする
第二章 Firestoreにデータを保存する
第三章 Firestoreからデータを取得するFirestoreを使う準備の流れ
1. config.jsファイルを作成する
2. エントリポイントを作成する
3. 初期データを取得する
4. まとめ1. config.jsファイルを作成する
srcディレクトリ配下に「firebase」ディレクトリを作成し、その中に「config.js」ファイルを作成します。
Firebaseのページに移り、「プロジェクトを設定」画面へ遷移します。
の下部にあるFirebase SDK snippetの構成にチェックを入れ、下に記載してあるコードをコピーしconfig.jsファイルに貼り付けます。
貼り付けた内容を他の画面で使うので、exportしておきます。
firebase/config.jsconst firebaseConfig = { apiKey: "******", authDomain: "******", databaseURL:"******", projectId: "******", storageBucket: "******", messagingSenderId: "******", appId: "******", measurementId: "******" }; export default firebaseConfigこちらの内容はGitHubなどに公開して問題ない内容のようですが、firestoreのセキュリティ設定をしておかないと簡単に書き込みをされてしまうので注意してください。(セキュリティ設定に関してはこちら)
2. エントリポイントを作成する
firebaseディレクトリ配下に「index.js」ファイルを作成し以下記述をします。
firebase/index.jsimport firebase from 'firebase/app' //firebaseを読み込み import 'firebase/firestore' //firebaseの中のfirestoreを読み込み import firestoreConfig from './congfig' //先ほど作成したconfigファイルを読み込み firebase.initializeApp(firesbaseConfig); //firebaseを初期化 export const db = firebase.firestore(); //初期化したfirebaseのfirestoreを使う3. Firestoreからデータを取得する
Firestoreからデータを取得していきます。まず、先ほど作成したdbをインポートします。
src/App.jsximport { db } from './firebase/index'useEffectを使い、ページ読み込み時に全データを取得するようにします。
async,await付きの即時関数で記述していきます。(即時関数について参考記事)src/App.jsximport React, {useState, useEffect} from 'react' import { db } from './firebase/index' const App = () => { const [dataset, setDataset] = useState({}); useEffect(() => { (async () => { const initDataset = {}; await db.collection('[チャットボットのjsonファイルで設定したキー]').get().then(snapshots => { snapshots.forEach(doc => { const id = doc.id const data = doc.data() initDataset[id] = data }) setDataset(initDataset) }) })() },[])ここで行っていることは以下です。
- collectionにアクセスし、データ(doc)を取得(データはsnapshotsに全て格納される)
- snapshotsの中身をforEachで回し、id,dataを取り出す
- 取り出したidをキーにinitDatasetの中にデータを格納する
あとは任意の場所でinitDatasetからidをキーにデータを取り出して使います。
4. まとめ
この章ではエントリポイントを作成し、Firestoreに格納したデータを取得しました。
今回初めて使ったみたのですが、記述すべき内容が把握できればとても簡単にできることがわかりました。手軽にバックエンド環境を用意したい方にはお勧めです!
- 投稿日:2020-10-11T10:07:48+09:00
Firebaseを使ってみた 〜第二章 Firestoreにデータを保存する 〜
React Hooksを使いチャットボットアプリを作成しています。
この章ではAPIを使いFirestoreにチャットボットアプリで使うデータを保存していきます。
第一章 サービスをデプロイする
第二章 Firestoreにデータを保存する
第三章 Firestoreからデータを取得するFirestoreにデータを保存する までの流れ
1. データファイルを作成する
2. Cloud Functionsをインポートして初期化する
3. https関数を作成する
4. デプロイ する
5. APIを叩く
6. まとめ1. データファイルを作成する
json型のデータファイルを生成します。
(jsonファイルの書き方が分からない・・・という場合はこちら参考にしてみてください)私はチャットボットで使う応答内容やユーザーの選択肢などをjson型で作成しました。
2. Cloud Functionsをインポートして初期化する
Cloud Functionsをインポートし、Firebase Admin SDK を初期化します。
こちらを参考にしました。(jsの場合の書き方もありました)functions/src/index.tsimport * as functions from 'firebase-functions'; import * as admin from "firebase-admin"; admin.initializeApp(); const db = admin.firestore();3. https関数を作成する
APIからのレスポンスを返すための関数を作成します。
response、statusCode、bodyを受け取ります。functions/src/index.tsconst sendResponse = (response: functions.Response, statusCode: number, body: any) => { response.send({ statusCode, body: JSON.stringify(body) }) }外部から関数を呼び出すため「export」をつけます。
今回はすべて「POST」を使うので、POST以外はエラーになるよう記述します。functions/src/index.tsexport const addDataset = functions.https.onRequest(async(req: any, res:any) => { if(req.method !== 'POST') { sendResponse(res, 405, {error: 'Invalid Request'}) } else { const dataset = req.body for(const key of Object.keys(dataset)) { const data = dataset[key] await db.collection('contents').doc(key).set(data) //'contents'の部分は任意のcollection名でOKです } sendResponse(res, 200, {message: 'Successfully added dataset!'}) } })参考:https://firebase.google.com/docs/functions/http-events?hl=ja
余談ですが、collection、document、dataについて曖昧な場合はこちらのページに図で解説があるので見てみてください。
4. デプロイ する
デプロイ コマンドを実行します。
$ firebase deployデプロイ 完了後、FirebaseのFunctionsに先ほど作成した関数名でデータが生成されます。
「リクエスト」の下に記述されているURLをコピーしておきましょう。(次で使います)
5. APIを叩く
1.で作成したデータファイルがあるディレクトリまで移動します。
移動したら、以下のcurlコマンドでAPIを叩きます。curl -X POST -H "Content-Type:application/json" -d @[作成したデータファイル名].json [先ほどコピーしたURL]ステータスコード200が返ってくれば成功です。
Cloud Firestoreにデータが格納されていることを確認します。
6. まとめ
この章ではFirebaseでプロジェクトを作成し、FirestoreにAPIを使ってデータを格納するところまで行いました。
続いてFirestoreに格納したデータを取得して使っていきます。(第三章へ・・・)
- 投稿日:2020-10-11T10:07:36+09:00
Firebaseを使ってみた 〜第一章 サービスをデプロイする 〜
React Hooksを使いチャットボットアプリを作成しています。(その辺の内容はいつかの記事で…)
バックエンド環境はFirebaseを使ってみました。設定内容やデプロイ までの過程を三章構成で記録しておきます。第一章 サービスをデプロイする
第二章 Firestoreにデータを保存する
第三章 Firestoreからデータを取得するFirebaseとは
Googleが提供しているBaaS(※)
バックエンド側の開発工数を抑え、アプリ側の開発に注力できるのがメリットです。※BaaS:backend as a serviceの略
アプリ開発におけるバックエンド環境を提供してくれるサービスデプロイ までの流れ
1. プロジェクトを作成する
2. 諸々設定をする
3. パッケージをインストールする
4. Firebaseにローカル環境を構築する
5. デプロイ する1. プロジェクトを作成する
Firebaseにログインしてプロジェクトを作成します。
(Googleアカウントでログイン可能)
ここのチェックはどちらでもOKだと思います。(私は一旦つけたままで・・)
ご自身のアカウントを選択して、「プロジェクト作成」をクリック
しばらくするとプロジェクトが生成されます。
2. 諸々設定をする
ここから諸々設定していきます。
まず、リソースロケーションの設定を行っていきます。「asia-northeast1」を選択します。
※ここで選択を間違えると後から修正できず面倒なので注意します。
そのまま同じ設定ページの下部にあるマイアプリを選択していきます。
今回はWebアプリを作成したいのでコードマークを選びました。
アプリのニックネーム(プロジェクト名と同じでいいと思います)を入力し、
「このアプリ〜」にチェックを入れて、「アプリを登録」をクリックします。
「Firebase SDKの追加」〜など全て「次へ」で遷移をし、最後に「コンソールに進む」を選択します。
3. パッケージをインストールする
firebase-toolsをグローバルインストールします。(すでにインストール済みの場合は対応不要です。)
npm install -g firebase-tools作業ディレクトリに移動し、以下のコマンドを実行します。
npm install --save firebase完了後、package.jsonファイルに最新のfirebaseが追加されたことが確認します。
4. Firebaseにローカル環境を構築する
以下のコマンドを実行してFirebaseにログインします。
firebase login以下の内容を聞かれるので、そのままEnterを押して許可します。
その後Firebaseのアクセス許可画面が出力されるので、同じく許可をします。成功画面を確認してターミナルに戻ります。? Allow Firebase to collect anonymous CLI usage information? (Y/n)次に以下のコマンドを実行し、先ほど作成したFirebaseの環境へローカルの内容を接続させます。
firebase init「FIREBASE」の文字が出力されれば成功です。
続いて以下設定をしていきます。まず1つ目、どのサービスを使うか選択します。
矢印キーで移動、spaceキーで選択、Enterキーで確定できます。
今回私は「Firestore」、「Functions」、「Hosting」の3つを使いました。? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection) ❯◯ Database: Deploy Firebase Realtime Database Rules ◯ Firestore: Deploy rules and create indexes for Firestore ◯ Functions: Configure and deploy Cloud Functions ◯ Hosting: Configure and deploy Firebase Hosting sites ◯ Storage: Deploy Cloud Storage security rules ◯ Emulators: Set up local emulators for Firebase features ◯ Remote Config: Get, deploy, and rollback configurations for Remote Config先ほどFirebaseの中でプロジェクトを作成したので、「Use an existing project」を選択、作成したプロジェクト名を選びます。
? Please select an option: (Use arrow keys) ❯ Use an existing project Create a new project Add Firebase to an existing Google Cloud Platform project Don't set up a default project以下質問が続きますが、特にデフォルトで問題ないのでそのままEnterで進みます。
? What file should be used for Firestore Rules? (firestore.rules) ? What file should be used for Firestore indexes? (firestore.indexes.json)Cloud Functionsをどの言語で作るか聞かれます。使いたい方を選択します。
その後選択した言語により諸々聞かれますがそのままYES(Enter)で進みます。? What language would you like to use to write Cloud Functions? (Use arrow keys) ❯ JavaScript TypeScript本番用のフォルダを聞かれます。デフォルトは「public」ですが、
今回create-react-appで作ったReactのサービスをデプロイ したいので、ここは「build」を入力します。? What do you want to use as your public directory? (public)デフォルトはNOですが、今回シングルページ で作成したいのでYESで進みます。
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N)エディタを見てもらうと以下のファイルが生成されていることを確認できます。
以上で構築終了です!
5. デプロイ する
ターミナルで以下コマンドを実行します。
まだビルドしていない場合は先に「$ npm run build」を行い、下記コマンドを実行します。firebase deploy完了後、Hosting URLが生成されるのでそちらをブラウザで確認します。
6. まとめ
以上でFirebaseへのサービスデプロイ が完了しました。
いくつかの設定を行うだけで簡単にデプロイ ができました。続いてFirestore(データベース)に使用するデータを保存していきます。(第二章へ・・・)7. APPENDIX
- firestoreのセキュリティを見直す
自由に書き込みができないように設定します。詳しいセキュリティ内容は こちらから確認できます。firestore.rulesservice cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, allow write: if request.auth.uid != null; } } }
- 投稿日:2020-10-11T04:51:34+09:00
LaravelでReactを使う私的まとめ
Laravel Mix
- フロントエンドのアセットをコンパイル、バンドルしてくれる
- 中身はwebpackでwebpackの設定をわかりやすく掛けるようにラッピングしてある
- sass,babelなどは最初から用意されている
バンドル
バンドルとは、束(ねる)、塊などの意味を持つ英単語で、単体でも提供可能な製品やサービスを、複数組み合わせてセットで販売したり、別の製品やサービスに付属して販売、提供することをこのように呼ぶ。
引用:バンドル 【 bundle 】つまり違うものを組み合わせてくれるってことかな
Laravel Mixの実行
npm run dexnpm run dev を実行すると、
package.jsonに書いてあるスクリプトが実行され、
設定ファイルに記述したコンパイルやバンドルが実行される。npm run production の場合は圧縮されたファイルが出力される。
引用:Laravel Mixとは?webpackをより便利に、簡単に。Laravel以外でも使えるよ。npm run watch関連ファイルを監視する
変更を感知すると自動的に再コンパイル
webpack.mix.js
ファイルSass
saasメソッドはSassをCSSコンパイル
mix.sass('resources/assets/sass/app.scss', 'public/css');ページを作ってみる
resource/js/app.js/** * Next, we will create a fresh React component instance and attach it to * the page. Then, you may begin adding components to this application * or customize the JavaScript scaffolding to fit your unique needs. */ //require('./components/Example'); require('./components/index'); //ここを書き換える次に、すべてのルーティングをindex.balde.phpに集中させる
web.phpRoute::get('/{any}', function(){ return view('index'); })->where('any', '.*');bladeファイルを作成
index.blade.php<!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>Title</title> </head> <body> <div id="root"> {{-- <example-component></example-component> --}} </div> <script src="{{ asset('/js/app.js') }}"></script> </body> </html>これでreact-router-domによるルーティングに対応できました。
参考:LaravelにReactを導入する時の手順〜ルーティングの設定
参考
- 投稿日:2020-10-11T02:24:23+09:00
React Profiler onRenderコールバックの引数の要素のそれぞれに名前を付ける
render( <Profiler id="header" onRender={(...args) => { const argsObj = [ "id", "phase", "actualDuration", "baseDuration", "startTime", "commitTime", "interactions" ].reduce((acc, cur, index) => ({ ...acc, [cur]: args[index] }), {}); console.log(argsObj); }} > <Hoge /> </Profiler> ); // このような出力になる { actualDuration: 0.07000000186963007 baseDuration: 0.050000002374872565 commitTime: 181.57500000233995 id: "hoge" interactions: Set(0) {} phase: "mount" startTime: 178.71000000013737 }
- 投稿日:2020-10-11T01:25:52+09:00
React Material UI + Node.js expressのアプリ構築手順をまとめた
はじめに
フロントエンドがReact(Material UI)、バックエンドがNode.js expressのアプリを構築することがあったので、(何番煎じか分かりませんが)備忘録に手順を残します。
環境
- Windows 10
- Node.js v12.16.3
- npm 6.14.4
- yarn 1.22.4
手順
ディレクトリ作成
# アプリのコードを管理するディレクトリを作成 mkdir app cd app # クライアント、サーバーのコードを配置するディレクトリを作成 mkdir client serverフロントエンド:React, Material UI の導入
cd client npx create-react-app my-app ※my-app=アプリ名 ※npxはnpm 5.2 から利用できるパッケージランナーツール cd my-app yarn add @material-ui/core --save # アプリ内でアイコンを使用したい場合はこれもインストールする。回線が遅いとインストール時にタイムアウトが発生する可能性があるため、タイムアウトの時間を長めに設定しておく。 yarn add @material-ui/icons --save --network-timeout 1000000000※動作確認は後ほど実施
バックエンド:express の導入
cd ../.. cd server npm init (対話式で色々と入力するものがある。こだわりなければ全てEnterでよい。) npm install express --save type nul > server.js (macではtouch server.js かな? 単にsever.jsというファイルを作成しているだけ。)server.jsをテキストエディタで開いて下記のコードをコピペする。
server.jsconst express = require('express'); const path = require('path'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); // Reactのアプリ名によってはディレクトリ名を一部変更する app.use(express.static(path.join(__dirname, '../client/my-app/build'))); app.listen((process.env.PORT || 8000), () => { console.log(`Listening on port ${PORT}`); });動作確認
フロントエンド
- 開発用サーバーの起動
cd client/my-app yarn starthttp://localhost:3000 にアクセスしてこのような画面が表示されれば成功です。
yarn start
を実行中にApp.jsなどを変更して保存すると自動でコンパイルをしてページも自動でリロードされます。フロントの開発中は
yarn start
で開発用サーバーを起動させつつ、バックエンドのexpressのサーバーも起動させてREST APIの呼び出しをするのが良いと思います。
- ビルド
コードをビルドして、静的なファイル(html, jsファイルなど)を出力します。
yarn buildデフォルトでは
app/client/my-app/build
にビルドされたファイルが出力されます。
このフォルダをexpressのstaticフォルダとして設定しておくと、 http://localhost:8000 で表示することが出来ます。バックエンド
- サーバー起動
cd server node server.jshttp://localhost:8000 にアクセスして、http://localhost:3000 と同様の画面が表示されれば成功です。
おまけ
Material UIの Button component Icon componentを組み合わせた例です。
Material UIのIconの参照先: https://material.io/resources/icons/?icon=check_circle_outline&style=baseline
App.jsimport React from 'react'; import './App.css'; import { Button } from '@material-ui/core'; import CheckCircleOutlineIcon from '@material-ui/icons/CheckCircleOutline'; function App() { return ( <div className="App"> <Button variant="contained" color="primary"> <CheckCircleOutlineIcon /> please click! </Button> </div> ); } export default App;App.css.App { padding-top: 100px; text-align: center; }参考サイト