- 投稿日:2020-09-14T23:51:19+09:00
Vue.js使いの自分がReact + TypeScriptにコンバートするためにやったこと(まだ途中)
タイトル通りの話で, 今まで2年ちょいVue.js(含むNuxt.js)使いだった自分がReact + TypeScriptの組み合わせを覚えて仕事にしよう!...という目標に向けて何をしたかについてまとめました.
- React + TypeScriptの組み合わせでちゃんと開発したい&覚えたい人
- Vue.js等, 他のJavaScriptライブラリ・フレームワークと二刀流を目指している人
- SPA(Single Page Application)開発をちゃんとやりたい人
の参考になれば幸いです.
なおコードスニペット的なのは一切ないです.
が, これから学習する方の役に立つと嬉しいです.
わたし(shinyorke)のJavaScript/SPA歴
- 昔から仕事や趣味⚾️開発でJavaScript, JQuery, Bootstrapは触っていました.
- JavaScriptは自力で調べながらどうにかやれます.
- 前職でVue.jsを2年近くやったのでSPAについてはそれなりに開発経験あります.
- Nuxt.jsでゼロベースからSPAを二回ほど実装・ローンチしました.
- npmとかyarnの意味はわかってます&環境もnvmで切り替えながらやれるレベルなのでそのへんのエコシステム周りは初心者ではないです(強くもないけど).
なお, Vue.jsのときにやったネタはブログにまとめています.
https://shinyorke.hatenablog.com/entry/hello-nuxt-coreui
https://shinyorke.hatenablog.com/entry/vue-django-hateoas
https://shinyorke.hatenablog.com/entry/front-app-and-vuejs
React + TypeScriptになれるまで
やったことを時系列で.
なお, まだ途中です!
Reactの公式チュートリアル
会社のつよつよフロントできるマンたちのオススメだったので素直に乗って写経しました.
https://ja.reactjs.org/tutorial/tutorial.html
ゲーム完成まで楽勝でいきました.
構成とかどういった意味なのか?的なのをチュートリアルと書いたコードを読みながら理解.
ただ, 肝心なComponentのライフサイクルだの状態遷移だのといった所はわかったようなわかんないような?でした.
書籍を写経してSlack(っぽい)アプリを自前で実装する.
ゲームよりも実践的なアプリを作ると慣れるかな?と思い, 昔読んだ書籍をもう一度掘り返しました.
React, Angular, Vue.js, React Nativeを使って学ぶ はじめてのフロントエンド開発
2年ちょっと前の本なのでそのままのコードで動かんやろ...という不安はあったものの, まあ自己解決できるだろっていう謎理論でそのままスタート.
サーバーアプリを作る(写経)
本編のSlack(風)チャット・クライアントアプリを作る前に, 書籍の説明通りチャットのサーバー部分をFirebase + Expressで作りました.
これについては, ほぼ書籍通りの写経で完了. これは意外だった.
唯一, デプロイができなかったぐらいですかね. 無料プランじゃできないぞ的な(おそらく書籍リリース時はできてた).
ただ, デプロイできなくてもローカルサーバーとして立ち上げて開発できたので別に困らなかったです.
ちなみにFirebaseをゼロから使うのは今回がはじめてでした. 思わぬ所で新しい道具を覚えた.
本丸のReact + TypeScript製チャット・クライアント開発
書籍を見ながらゼロから写経しました, 途中動かないとか色々ありました.
特にライブラリのバージョンがきつかった...書籍通りで動かん!と思い,
https://github.com/okachijs/jsframeworkbook/tree/master/3_6_react
こちらのpackage.jsonを見ながら調整.
あとnodeのLTS(12系)じゃダメだったので8系に落として動かしました, この騒動で半日ほどドハマリ.
これはまあしょうがないか...
その後は順調に行きました, 型安全のJavaScriptは精神衛生上すごく良いというのがよくわかった.
これからやりたいこと
Vue.jsで作ったやつをReact + TypeScriptで写経して本格的に慣れるとか, 今いくつか作りたいネタがあるのでそれをReact + TypeScriptでやるとか.
あと, 会社のプロダクトでいくつかReact + TypeScriptあるのでそこにコントリビュートとか考えています!
- 投稿日:2020-09-14T21:43:13+09:00
とても簡単なReactの良さが5分以内に分かる例
はじめに
Web開発のフロントエンドがjQueryからReactへ移った技術改革は、「仮想DOM」「DOM操作をしない」「コンポーネント志向」という文脈で持て囃されて語れます。
しかしこれらの何が嬉しいのか?という方も居ると思います。従来の私もそうでした。今ではこれらの有難みが分かりますが、実際にフロントエンドコーディング自体が想像しづらいと気付きづらいかなとも思います。
そこで今回はReactの感動に気づいてもらうことを目的に、簡素な例を用意しました。対象読者は、jQueryは使えるがReactは聞いたことがあり、JSXの書き方くらいは知ってるけどメリットがイマイチ...と思っている方です。
注意
・Reactに関わらずAngularやVue等も含めても成り立つのでしょうが、その2つはほとんど書けないので触れておかないことにします。
・細かい部分は端折り雰囲気重視です。
カウンターアプリ
まずは初期値は0で、ボタンを押すと値が増えていくアプリを作りたいと思います。
マークアップから用意していきます。<!DOCTYPE html> <html> <head> <title>Title</title> <!-- Required meta tags --> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> </head> <body> <p id="value"></p> <p><button id="increment">Increment</button></p> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script> <script src="js/index.js"></script> </body> </html>※小ネタ:VsCodeを使う際にjQueryを含んだ簡単なマークアップテンプレートを用意するには、Bootstrap 4, Font awesome 4, Font Awesome 5 Free & Pro snippets という拡張機能をインストールし、
b4-$
で入力補完すると手軽に生成できます。値の表示要素は
#value
、ボタンは#increment
と決めました。
これを素にJSの処理を書いていきます。// 初期値は0。それをvalueに表示させる var value = 0; $('#value').html(value); // ボタンをクリックしたら... $('#increment').on('click', function () { value = value + 1; // valueを1増加させて $('#value').html(value); // それを表示させる });ここでコードを眺めてみましょう。データの操作とDOMへのデータ反映に分かれていますね。
そこで、データ反映を行う部分をそれっぽい関数名にしてみましょう。var value = 0; render(); $('#increment').on('click', function () { value = value + 1; render(); }); function render() { $('#value').html(value); }こんな感じになりました。今の例では恩恵があるか微妙ですが、valueに相当するものが増えた場合にこれは威力を発揮するでしょう。
ところが、何となくrender()
が2箇所に現れていてスッキリしないと思いませんか?
value
の更新を行ったら、自動でDOMにも反映されていて欲しいですね...。願わくば、
var value = 0; render(); $('#increment').on('click', function () { value = value + 1; }); function render() { $('#value').html(value); }こんなものが理想ですが、実際に動きません。
それを実現してくれるのがReactです!
先程を同じカウンターをReactで作ってみましょう。
create-react-appと使ってプロジェクトを作ります。
ついでに、ES7 React/Redux/GraphQL/React-Native snippetsという拡張機能もインストールしておきましょう。npx create-react-app counter-react ...(省略)... cd counter-react npm run startデフォルトのマークアップが入っています。邪魔なので消しましょう。
index.css
とApp.css
の中身を空にします。create-react-appで生成したReactプロジェクトの初歩は、
以下のreturnされるdiv要素内にマークアップやロジック等の処理を書くことになります。import React from 'react'; import './App.css'; function App() { return ( <div> {/* ここに書く */} </div> ); } export default App;ではReact版のカウンターを早速作りましょう。
ReactはコンポーネントというものでUIを管理します。コンポーネント名はCounterを付けておきます。import React from 'react'; import './App.css'; function App() { return ( <div> <Counter /> </div> ); } export default App;このままでは
<Counter />
が存在しないのでコンパイラに怒られます。
そこで<Counter />
を定義していきます。Reactには
props
とstate
というパラメータがあります。前者は関数の引数、後者は関数のローカル変数のようなものです。(イメージ)
value
の性質はローカルなものとして、クラスコンポーネントを使ってstateを定義します。
ついでにrenderされるマークアップも用意します。※Hooksはこの記事ではスルーします
import React from 'react'; import './App.css'; class Counter extends React.Component { constructor(props) { super(props); this.state = { value: 0, }; } render() { return ( <div> <p>{this.state.value}</p> <p> <button>Increment</button> </p> </div> ); } } function App() { return ( <div> <Counter /> </div> ); } export default App;コンポーネントのコーディングが仰々しく面倒に思いますよね?
でも、拡張機能のスニペットを使えば楽々です。
コンストラクタはrconst
、render
メソッドはren
と入力してください。続いてクリック処理に移りましょう。メソッド名は
increment
と付けておきます。
ここで注意ですが、クラスに所属するメソッド名なのでthis
を忘れないでください。import React from 'react'; import './App.css'; class Counter extends React.Component { constructor(props) { super(props); this.state = { value: 0, }; } render() { return ( <div> <p>{this.state.value}</p> <p> <button onClick={this.increment}>Increment</button> </p> </div> ); } } function App() { return ( <div> <Counter /> </div> ); } export default App;まだ
increment
の中身が書いていないのでもう少し準備をします。
- クリックイベントで呼び出すメソッドには、
this.hoge = this.hoge.bind(this)
というおまじないがコンストラクタに必要です。- メソッドをクラス内に記述します。
import React from 'react'; import './App.css'; class Counter extends React.Component { constructor(props) { super(props); this.state = { value: 0, }; this.increment = this.increment.bind(this); } increment() {} render() { return ( <div> <p>{this.state.value}</p> <p> <button onClick={this.increment}>Increment</button> </p> </div> ); } } function App() { return ( <div> <Counter /> </div> ); } export default App;ようやく準備が整いました。カウントアップできるメソッドを記述しましょう。
this.state.value
を更新しますが、state
の更新にはsetState()
メソッドを使います。
Javaでメンバ変数を直接更新せずにsetterを使うようなルールです。
setState()
の書き方は用途によって2通りあります。// 前のstate値を更新に使わない場合: // 新しい値をセットしたオブジェクトを引数に渡す this.setState({ hoge: newValue }); // 前のstate値を更新に使う場合: // 前のstateを引数に取り、新しい値をセットしたオブジェクトを返す関数を // 引数に渡す this.setState((prevState) => ({ hoge: doFuga(prevState) }));今回は後者になります。
import React from 'react'; import './App.css'; class Counter extends React.Component { constructor(props) { super(props); this.state = { value: 0, }; this.increment = this.increment.bind(this); } increment() { this.setState((prevState) => ({ value: prevState.value + 1 })); } render() { return ( <div> <p>{this.state.value}</p> <p> <button onClick={this.increment}>Increment</button> </p> </div> ); } } function App() { return ( <div> <Counter /> </div> ); } export default App;
this.setState
ってなんだかタイポしそうですね。
でも、sst
と入力すれば補完してくれます。これで無事成功です。
ここで注目すべきは、DOMへの描画部分をわざわざ2回書かなくても良いことです。
値を変える処理の後は反映、また別の処理の後に反映...のような記述をしなくて構いません。
値が変わればDOMも勝手に書き換わってくれます。素晴らしいと思って頂けましたか?
薄い記事ですが、これを取っ掛かりにReactが普及すれば嬉しく思います。
- 投稿日:2020-09-14T21:40:53+09:00
Kubernetes: NodePortを利用したアプリの公開、デプロイ
0.アプリを公開したい
久しぶりに投稿します。今回はKubernetesでNodePort Serviceを利用してアプリを公開する方法を紹介していきます。
Kubernetesを使って試しに、気軽にアプリをデプロイしてみたい(お金はかけたくない。。。)!という方向けです。今回使用した環境はIBM Cloudですが、どのCloudでも同様にデプロイできると思います。Kubernetes環境の無料枠が一ヶ月で、期限が切れても再び構築することはできます。
無料枠ではIngressなどを使うことはできませんが、Serviceリソースの一つであるNodePortを利用してアプリを公開することはできます。Dockerコンテナの作成からKubernetes上へのデプロイまでを行なっているので、これらの一連の流れが掴めるようにはなってると思います。
前提
- IBM Cloud アカウントの取得
- IBM CloudのKubernetes上にクラスターを構築してあること
- DockerがインストールされていてDocker Hubのアカウントを持っている
- 公開してみたいアプリがあること(なんでもよし。今回作成するアプリに関しては以下の環境が必要)
- Node.js(node: v12.18.2, npm: 6.14.5)環境があること
- create-react-appコマンドを使えること
1.サンプルアプリのDockerコンテナの作成
今回はcreate-react-appで簡単に作成できるReactアプリをデプロイしてみようと思います。まずはコンテナ化して動作確認します。
1-1. Reactアプリ作成(create-react-appはインストールされている前提)
$ create-react-app my-react-app $ cd my-react-app1-2. Dockerfile作成
Dockerfileを以下のように作成し、my-react-appディレクトリ直下に配置します。
DockerfileFROM node:12 COPY . /app WORKDIR /app RUN npm run build && \ npm install -g serve CMD [ "serve" , "-s", "build" ]今回のコンテナ作成の流れとしてはproduction用の静的ファイルを生成し,それを静的ファイルサーバーを用いて実行するものになっています。
静的ファイルサーバー実行時、デフォルトでは5000番ポートを受け付けます。1-3. ビルドし、ローカルで動くことを確認する
$ docker build -t my-react-app:0.0.1 . $ docker run -p 5000:5000 my-react-app:0.0.1 INFO: Accepting connections at http://localhost:5000 #localhost:5000でreactアプリが動いていることができたらexit2.DockerHubにpushする
2-1. 'docker tag'で1で作成したイメージに自分のDocker Hubのアカウント名(レポジトリ名)を付与する
$ docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: <DockerHubアカウント名> Password: Login Succeeded $ docker tag my-react-app:0.0.1 <DockerHubアカウント名>/my-react-app:0.0.12-2. イメージをDocker Hubのレポジトリににpushする
my-react-app $ docker push <DockerHubアカウント名>/my-react-app:0.0.1 The push refers to repository [docker.io/bangdr2018/my-react-app] 24531b8429e8: Pushed ea8d003551da: Pushed 9cee2cb2fb8e: Mounted from library/node eb3f44bfde1e: Mounted from library/node 3b93aab45097: Mounted from library/node 174e334f3f46: Mounted from library/node cbe6bbd0c86f: Mounted from library/node ef5de533cb53: Mounted from library/node a4c504f73441: Mounted from library/node e8847c2734e1: Mounted from library/node b323b70996e4: Mounted from library/node 0.0.1: digest: sha256:f032be9c6a2530de810d1a29b75777a01655e7a23b64a7aa39e81f5154a82640 size: 26382-3. イメージがpushできたことDocker Hubのコンソール上で確認(アカウント名は念のため切ってます)
3. Kubernetesへのデプロイ、アプリの公開
3-1. kubectlコマンドのコンテキストを確認する。
コンテキストが存在しなかったり、ローカルなど異なるコンテキストとなっていた場合は、kubectlコマンドをダウンロードする
// すでにIBM Cloudに構築したKubernetesからkubectlコマンドをダウンロードしていた場合コンテキストは次のようになる $ kubectl config current-context <クラスター名>/<クラスターID>ダウンロードしていなかった場合はIBM Cloudコンソール上でクラスターのプロファイルを開き、「アクセス」の箇所に以下のようにkubectlコマンドのダウンロード方法が載っている(ibmcloudコマンドをすでに使用できる場合「CLIツールの一回かぎりのセットアップ」は不要)。
3-2. deployment.ymlの作成
以下のようにdeployment.ymlを作成。containerのimageに2でpushしたイメージを指定する
deployment.ymlapiVersion: apps/v1 kind: Deployment metadata: name: my-react-app-deployment spec: selector: matchLabels: app: my-react-app template: metadata: labels: app: my-react-app spec: containers: - name: my-react-app image: <DockerHubアカウント名>/my-react-app:0.0.1 resources: limits: memory: "128Mi" cpu: "500m" ports: - containerPort: 5000Podが生成、Runnningとなっていることを確認(Podの名前はデプロイメント名に付随する)
$ my-react-app $ kubectl get pods NAME READY STATUS RESTARTS AGE my-react-app-deployment-c4f95c7cd-rx8xt 1/1 Running 0 8s3-3. NodePortを利用したserviceを作成する
以下のようにservice.ymlを作成。selectorのラベル(app: my-react-app)とPodのラベル(app: my-react-app)を一致させる。
ポートの番号は30000-32767の間に指定する。service.ymlapiVersion: v1 kind: Service metadata: name: my-react-app-service spec: type: NodePort selector: app: my-react-app ports: - port: 5000 targetPort: 5000 nodePort: 30080 protocol: "TCP" name: "http-port"serviceが生成されていることを確認の確認(Podの名前はデプロイメント名に付随する)
my-react-app $ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-react-app-service NodePort 172.21.94.246 <none> 5000:30080/TCP 10s3-4. Nodeに割り振られているExternal IPを確認する
NodePort Serviceはその名の通り、:<ポート>で受信したトラフィックをコンテナに送信するものなので、nodeのEXTERNAL-IPを確認する。
// -o wideオプションで表示可能 $ kubectl get node -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP(これ!) OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME 10.144.194.234 Ready <none> 13d v1.17.11+IKS 10.144.194.234 159.122.xxx.xxx Ubuntu 16.04.7 LTS 4.4.0-187-generic containerd://1.3.43-5. 公開されたアプリをみてみる
さあ緊張の瞬間ですが:で公開されたアプリを見てみましょう。
公開できました!やりましたね!
おわりに
今回はアプリのコンテナ化からKubernetes上へのデプロイまでの一連の流れを紹介してみました。
結構簡単に、かつ柔軟にデプロイできると思いました。ただKubernetesのメリットとしてはこんなものではないので自分自身も勉強しつつ有益だと思ったらどんどん投稿していこうと思います。
次はKubernetesで構築したアプリの環境変数周りのリソースについて説明してみようかなと思ってます。
- 投稿日:2020-09-14T20:24:40+09:00
【React】公式ドキュメントの私的まとめ
公式の私的まとめ
この記事でのコードは公式を参考にしている。
イベント処理
Reactのイベント処理はブラウザのDOMと似ている
違いは以下
- Reactのイベントは小文字ではなくcamelCase
- JSXではイベントハンドラとして文字列じゃなくて関数を渡す
HTML<button onclick="activateLasers()"> Activate Lasers </button>React<button onClick={activateLasers}> Activate Lasers </button>このようにReactでは属性名がcamelCaseで、イベントが関数で渡されている
またReactではfalseを返してもデフォルト動作を抑制できない
<a href="#" onclick="console.log('The link was clicked.'); return false"> Click me </a>React では、以下のようになる
function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('The link was clicked.'); } return ( <a href="#" onClick={handleClick}> Click me </a> ); }e.preventDefault();として抑制している。
eはブラウザと五感を持っているReactはDOM生成後にaddEventListenerでイベントを追加する必要はない
代わりに最初にレンダーされるときにリスナを指定する。JSXのコールバックのthis
javascriptではクラスにメソッドはデフォルトでバインドされない
this.handleClickへのバインドを忘れるとonClickで実際に関数が呼ばれたときに、thisはundefindとなる。Reactに限らずjavascriptはそういうもの
onClick={this.handleClick}のように()をつけないでメソッドを参照するときそのメソッドはバインドしておく必要があるとりあえずイベントを使うときはバインドしておけばいいと思う
イベントハンドラに引数を渡す
idという行のIDがあるとき、以下はちゃんと動作する
//bind <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>ReactイベントeはIDの2番めの引数として渡される。
id以降の追加の引数は自動的に転送される。意味ワカンネ
条件付きレンダー
以下は公式のログイン状況でどちらかを表示するコンポーネント
function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } function LoginButton(props) { return ( <button onClick={props.onClick}> Login </button> ); } function LogoutButton(props) { return ( <button onClick={props.onClick}> Logout </button> ); } class LoginControl extends React.Component { constructor(props) { super(props); this.handleLoginClick = this.handleLoginClick.bind(this); this.handleLogoutClick = this.handleLogoutClick.bind(this); this.state = {isLoggedIn: false}; } handleLoginClick() { this.setState({isLoggedIn: true}); } handleLogoutClick() { this.setState({isLoggedIn: false}); } render() { const isLoggedIn = this.state.isLoggedIn; let button; if (isLoggedIn) { button = <LogoutButton onClick={this.handleLogoutClick} />; } else { button = <LoginButton onClick={this.handleLoginClick} />; } return ( <div> <Greeting isLoggedIn={isLoggedIn} /> {button} </div> ); } } ReactDOM.render( <LoginControl />, document.getElementById('root') );以下の手順で切り替えをしている。
- Reactがを実行してLoginControlクラスのコンストラクタを実行する。そこでは2つログイン状況を変更するsetStateを実行する関数がバインドされている。更にstateの初期値を設定する。
- Reactはその後render()を実行。ログイン状況を判定してボタン要素を再描画するかを決めている。
- render()内でそこでGreetingクラスが呼ばれる。その際に、isLoggedInプロパティ(今のログイン状況の値が入っている)をpropsとして渡している。そこでも判定して表示するReactエレメントを返してボタン要素も描画する。 ##論理 && 演算子による 他の方法で条件付きのレンダーができるが、今は混乱するからif文の方法だけにしておく。
リストとkey
以下はjavascriptでリストを変換する方法
const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map((number) => number * 2); console.log(doubled);上記は値を2倍にした配列を生成している。
Reactも同様にリスト変換できる複数のコンポーネントをレンダリング
const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li>{number}</li> );エレメントを配列に格納している
function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') );上記は先のコードを同じ出力
<li key={number.toString()}>
を書かないと
Warning: Each child in a list should have a unique "key" prop.
という警告を受ける
これはkeyを与えとという意味key
これはReactがどの要素が変更されたかをReactが認識するために使っている
フォーム
通常のフォームを使うとページ遷移が起こるが大半はそうなってほしくない
ここでは制御されたコンポーネントなるテクニックを学ぶらしい制御されたコンポーネント
HTMLではフォーム要素は自身で状態を保持している
Reactは変更されうる状態はstateに保持されるReactのstateを信頼できる雄一の情報とすることで、ユーザのフォーム入力で起こることも制御できる。
これを制御されたコンポーネントというらしいがイマイチピンとこない以下はその例
class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } }ポイント
- inputのvalueをthis.state.valueとしている
- onChangeで入力するたびにstateが変わることでフォームを送信する頃には最終入力値が送信される
制御されたコンポーネントでユーザ入力がReactのstateで制御できる
textarea
<textarea value={this.state.value} onChange={this.handleChange} />Reactではvalue属性を使う
file input
<input type="file" />これは読み取り専用で制御はできない
複数入力の処理
それぞれのname属性を追加すればevent.target.nameで処理の選択ができる
- 投稿日:2020-09-14T18:01:48+09:00
Reactでボタンが押された時にaxiosでAPIコールする方法 with Bootstrap
環境
npm 6.14.8
手順
テストコールするためのプロジェクトを作成
create-react-app test_call_api cd test_call_api npm start
を実行すると以下のページにアクセスするとデフォルトのreactのトップ画面が表示されます。
API実行処理を動かすために必要なものをインストール
今回はAPI実行用にaxiosと画面を綺麗にするbootstrapをインストールします。
インストール後はnpm audit fix
する。npm i axios bootstrap react-bootstrap npm audit fix vim src/App.jsApp.jsの中身を実装
以下の様に実装しました。今回は世界一簡単なAPIの祝日APIから取得いたします。
https://holidays-jp.github.io/import axios from 'axios'; import React, { Component } from 'react'; import { Container, Row, Col, Button, Table, Form } from 'react-bootstrap'; const API_URL = 'https://holidays-jp.github.io/api/v1/date.json'; /** APIのレスポンスは以下を想定する { "2017-01-01": "元日", "2017-01-02": "元日 振替休日", "2017-01-09": "成人の日" } */ export default class App extends Component { // 初期値を設定 constructor(props) { super(props); this.state = { api_data: [], // 今回test_paramは使用しないが、パラメータ設定方法の一つとして記載する test_param: '' }; } /** * APIを実行する */ handleTestCallApi() { axios // パラメータを指定する場合は以下のように設定 // { params: { test_param: this.state.test_param }} .get(API_URL) .then((results) => { const data = results.data; // APIレスポンスを取得する this.setState({ api_data: data, }); }, ) .catch((error) => { if (error.response) { // 200系以外の時にエラーが発生する console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { console.log(error.request); } else { // 上記以外のエラーが発生した場合 console.log('Error', error.message); } }); } /** * 変更があった場合、test_paramを更新する * 今回test_paramは使用しないが、パラメータ設定方法の一つとして記載する */ handleChange(event:InputEvent) { this.setState({ test_param: event.target.value, }); } render() { return ( <div className="app"> <Container> <h1>API実行する画面</h1> <Form> <Row> <Col className="submit-form"> <Form.Group controlId="formBasicShopId"> <Form.Control value={this.state.test_param} type="text" name="test_param" onChange={(e) => { this.handleChange(e); }} /> </Form.Group> </Col> </Row> <Button onClick={() => this.handleTestCallApi()}>Exec</Button> </Form> <br /> <Table> <thead data-type="ok"> <tr><th>date</th><th>何の日</th></tr> </thead> <tbody> {Object.keys(this.state.api_data).map(key => ( <tr key={key}> <td>{key}</td><td>{this.state.api_data[key]}</td> </tr> ))} </tbody> </Table> </Container> </div> ); } }画面を開いてみます。
http://localhost:3000/なんか綺麗な画面になっていません、Bootstrapがうまく動いていない様です。
vim public/index.htmlindex.htmlのmetaタグの下に以下の様にbootstrapを読み込む必要がありました。
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />これでアクセスし直します。
うまくいったようです。
Execボタンを押すと祝日情報が表示される様になっています。おわりに
react.jsでAPIを実行する方法がいまいち調べてもわからなかったのでまとめました。
- 投稿日:2020-09-14T17:56:48+09:00
create-react-appでtsyringeを使う方法
「create-react-app」で作ったプロジェクトに「tsyringe」を導入する際に、
「TypeInfo not known for ~」というエラーが出てしまい、解決に苦戦してしまったので備忘録として残します。create-reacdt-appでプロジェクトを作成
$ npx create-react-app sample --template typescript $ yarn add tsyringe reflect-metadatatsconfig.json{ "compilerOptions": { ~ "experimentalDecorators": true, "emitDecoratorMetadata": true }, ~ }cracoでbabelプラグインを追加する
「create-react-app」そのままでは「tsyringe」は使用できないため、「craco」というパッケージを使いました。
これは「Create React App Configuration Override」の略で、babelの構成などを上書きできるパッケージです。https://github.com/gsoft-inc/craco
yarn add -D babel-plugin-transform-typescript-metadata cracopackage.json"scripts": { "start": "craco start", "build": "craco build", "test": "craco test" }craco.config.jsmodule.exports = function ({ env: _env }) { return { babel: { plugins: ["babel-plugin-transform-typescript-metadata"], }, }; };
- 投稿日:2020-09-14T15:51:30+09:00
React appをFirebaseにデプロイ
Reactとは
Reactとは、UIを作成するための、Facebookが開発したJavaScript用ライブラリです。Facebook、Yahoo、Qiita、Wantedlyなども採用しています。
詳細: https://ja.reactjs.org/Reactのコンセプト
Declarative(宣言的である)
Component-Based(コンポーネント思考がベースになっている)
Learn Once, Write Anywhere(他の分野にも適応できる)
Firebaseとは
Googleが運営するクラウドプラットフォーム。無料枠があり、HerokuのGoogle版。
詳細: https://firebase.google.com/?hl=jaFirebaseの導入
以下のコマンドをターミナルで実行し、Firebase-CLIをインストール。
$ npm install -g firebase-toolsGoogleアカウントを紐づけ
$ firebase login // 実行後、メールアドレスなどを入力するFirebaseの初期化
以下を実行してFirebaseを初期化
$ firebase init初期化後、以下のようにターミナルから、色々聞かれるので
######## #### ######## ######## ######## ### ###### ######## ## ## ## ## ## ## ## ## ## ## ## ###### ## ######## ###### ######## ######### ###### ###### ## ## ## ## ## ## ## ## ## ## ## ## #### ## ## ######## ######## ## ## ###### ######## ❯◯ 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◯ Hosting: Configure and deploy Firebase Hosting sites
を選択し、 スペースキー を押した後に Enter
option
次にoptionを聞かれるので
? 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すでにFirebaseプロジェクトがある場合
Firebase内に、すでにプロジェクトを作成してたら以下を選択し Enter
プロジェクトを選択し EnterUse an existing project
Firebaseプロジェクトがない場合
初めて作成する時には以下を選択し Enter
Create a new project
次にFirebaseのブラウザからプロジェクトを作成する
プロジェクトの作成は以下参照
https://qiita.com/Watakatsu/items/667f45081a6dfbc11074プロジェクトとローカルのフォルダを紐づけ
$ firebase use --addデプロイ
$ firebase deploy以上
- 投稿日:2020-09-14T13:16:39+09:00
【React】ボタンクリックで別のDOM要素のイベントを起動する方法
はじめに
ボタンクリックで別のDOM要素のイベントを起動する方法についてです。
Material Uiの
<Button />
など、あらかじめカスタムされたコンポーネントだと別のDOM要素を紐付けるカスタムは面倒です。
ここではuseRef()
を使用し、onClick
でDOMの参照に対する操作を行うことで解決します。※通常は
<Form />
要素を使用することで複雑な実装なく動作します。シチュエーション
ボタン(
<Button />
)と、透明な入力ボックス(<input />
)がある
<input type="file" />
を使用したファイルアップロードをボタンから行えるようにしたい。やりたいこと
ボタンをクリックしたら、入力ボックスがクリックされた挙動をさせたい
関数コンポーネント<Button onClick={handleClick} > <input type="file" style={{display: 'none'}} />
方法
React.useRef()
を使って、入力ボックス(<input />
)の参照を得るonClick
したら、関数内で参照をクリックさせる関数コンポーネントconst inputRef = React.useRef(); const handleClick = () => inputRef.current.click(); // ..... <Button onClick={handleClick} > <input type="file" ref={inputRef} style={{display: 'none'}} />まとめ
React.useRef()
を使うことで、操作したいDOMへの参照を得るonClick
内で参照に対する操作を行うこうすることで、あるボタンから別のDOM要素のイベントを起動できる。
- 投稿日:2020-09-14T08:57:31+09:00
create-react-appで作ったwebサイトからサンプルコードを漏れなく消す
React勉強中のある日...
よし、Reactを使って自分のポートフォリオサイトを作ってみるぞー!
create-react-app
ってコマンドを使えばサクッと環境構築できるっぽいぞ!!
Typescriptは使いたいね〜% npx create-react-app ham-portfolio --template typescript Creating a new React app in /Users/ham/ham-portfolio. ...(略) We suggest that you begin by typing: cd ham-portfolio yarn start Happy hacking! %
よしできた!!
書いてある通りyarn start
や〜とりあえず画面は表示できたので環境構築成功!
マジで簡単にできるなー!!
かっこいいポートフォリオを作るぞー!!!(数日後...)
やっと完成したーーー!!!!
Firebase Hostingとか適当なホスティングサービスで公開したら経歴書代わりにも使えそうやな!!!!!
...
ちょっと待って下さい!!!
そのサイト、create-react-app
で生成されたサンプルコードが残りまくっていますよー例えばタブのところに注目です。
reactのアイコンが表示され、タイトルが"React App"になっています。
個人で使うだけなら気にしなくても良いですが、公開するのであればサンプルコードのままになっている部分は消しておきたいですね。
この記事ではcreate-react-app
で作ったWebアプリで最低限修正すべきところを修正していきます。ライブラリのバージョン
この記事で使われているライブラリーのバージョンは下記の通り。
% npm --version 6.14.8 % create-react-app --version 3.4.1
修正開始
それではサンプルコードを修正していきます。
public/favicon.ico
Chromeのタブに表示されていたReactのアイコンです。
他にもアドレスバーに表示されたり、ブックマークに表示されたりと意外に露出の多いアイコンです。
適切なアイコンに変更しておきましょう。通常、ファビコンは16x16ピクセルの GIF、 PNG、または ICO 形式で保存されます。
https://developer.mozilla.org/ja/docs/Glossary/Favicon
public/index.html
title
サイトのタイトルです。
Chromeではタブに表示されています。
Googleの検索結果やSNSでシェアするときにも表示されるので修正しておきましょう。- <title>React App</title> + <title>ham's portfolio</title>description
サイトの説明です。
こちらもGoogleの検索結果やSNSでシェアするときにも表示されるので修正しおきましょう。<meta name="description" - content="Web site created using create-react-app" + content="hamのポートフォリオです!!" />lang
日本語サイトであれば
lang=ja
に変更しておきましょう。- <html lang="en"> + <html lang="ja">apple-touch-icon
iPhoneのSafariで"ホーム画面に追加"をした時に表示される画像です。
ついでに変えておきましょう。- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> + <link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.jpg" />メタタグ追加
サンプルコードを消すという趣旨からはずれますが、作ったWebサイトをFacebookやTwitterなどのSNSでシェアした時に適切な情報が表示されるようにメタタグを追加しておきましょう。
メタタグはogタグを追加します。
詳細は下記を参照してください。
https://developers.facebook.com/docs/sharing/webmasters/?locale=ja_JP上記にも書いてありますが、シェアデバッガーを使うとタグが正しく設定できているか確認できます。
必ず確認しましょう。twitter用のタグは下記を参照してください。
https://developer.twitter.com/ja/docs/tweets/optimize-with-cards/guides/getting-startedtwitterもCard validatorを使うことでタグが正しく設定できているか確認できます。
こちらも必ず確認しましょう。今回は下記のように追加してみました。
app_idはFacebook Developerで簡単に発行できます。public/index.html<meta property="og:title" content="ham's portfolio" /> <meta property="og:type" content="website" /> <meta property="og:url" content="https://ham-portfolio.web.app/" /> <meta property="og:image" content="https://ham-portfolio.web.app/ham512.jpg" /> <meta property="og:image:alt" content="ham" /> <meta property="og:site_name" content="ham's portfolio" /> <meta property="og:description" content="hamのポートフォリオです!!" /> <meta property="fb:app_id" content="1975794755877620" /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:site" content="@hamchance0215" /> <meta name="twitter:creator" content="@hamchance0215" /> <meta name="twitter:title" content="ham's portfolio" /> <meta name="twitter:description" content="hamのポートフォリオです!!" /> <meta name="twitter:image" content="https://ham-portfolio.web.app/ham512.jpg" /> <meta name="twitter:image:alt" content="ham" />コメントを消す
HTML内に様々な説明コメントが入っています。
ビルドするとコメントは削除されるのでHTMLソースを見た時に表示されるわけではないですが、Githubなどでコードを公開するのであれば消しておきましょう。ソースを第三者が見た時に、下記のような初期構築時の説明コメントが残っているとチュートリアルとかをサクッとやっただけだなーと思われることがあります。
- <!-- - This HTML file is a template. - If you open it directly in the browser, you will see an empty page. - - You can add webfonts, meta tags, or analytics to this file. - The build step will place the bundled scripts into the <body> tag. - - To begin the development, run `npm start` or `yarn start`. - To create a production bundle, use `npm run build` or `yarn build`. - -->
Service Worker
create-react-appで作成するとService Workerのコードが入っています。
Service Workerを有効にすると、Webサイトをアプリのように振る舞うようにすることができます。
私は初めて見たときは得体のしれないものでめんどくさそうだと思い無視してしまいましたが簡単に有効にできるのでやってみましょう!Service Workerについては下記を参照
https://developers.google.com/web/fundamentals/primers/service-workers?hl=jasrc/index.tsx
コメントに書かれている通り、
unregister()
をregister()
に修正すればService Workerが有効になります。src/index.tsx// If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA - serviceWorker.register(); + serviceWorker.register();manifest.json
Service Workerを有効にしてPWAとして動作させるためにmanifest.jsonで名称やアイコンなど各種情報を設定する必要があります。
マニフェストファイルについては下記参照
https://developer.mozilla.org/ja/docs/Web/Manifest今回は下記のように修正してみました。
public/manifest.json{ "short_name": "ham's p", "name": "ham's portfolio", "icons": [ { "src": "favicon.ico", "sizes": "48x48", "type": "image/x-icon" }, { "src": "ham144.png", "type": "image/png", "sizes": "144x144" }, { "src": "ham192.jpg", "type": "image/jpeg", "sizes": "192x192" }, { "src": "ham512.jpg", "type": "image/jpeg", "sizes": "512x512" } ], "start_url": "/", "Scope": "/", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" }正しく設定されているかは、Chrome Dev ToolsのApplicationタブ、 Application > Manifestで確認することが出来ます。
情報に間違いがある場合は警告が表示されるので、警告がなくなるように修正しましょう。README.md
サイトを公開するだけであれば必要ありませんが、GitHubも公開するのであればREADMEも修正しておくと良いでしょう。
デフォルトではcreate-react-app
やReact自体の説明や使えるscriptの説明が記載されています。
作ったサイトの説明や公開しているURLを追記すると良いと思います。修正後の確認
ググっても大丈夫!!
※このQiita用に作ったページはクローリングされなかったのでイメージはサンプルです・・・
きちんと内容のあるサイトを作るとGoogleもクローリングしてくれます!
サイトを作ったらGoogle Search Consoleで確認してみましょう。
https://support.google.com/webmasters#topic=9128571Service Workderを有効にしてマニフェストファイルもきちんと設定しているのでブラウザアプリとして追加することも出来ます!!
- 投稿日:2020-09-14T00:25:39+09:00
react-diff-viewer を使って GitHub 風の diff を表示する
react-diff-viewer は React アプリケーションで GitHub 風の Diff を簡単に表示することできるライブラリです。
公式のデモはこちらです。
React.js で Diff を表示するライブラリは他にも、react-diff-view などがありますが、こちらは react-diff-viewer に関する記事になりますのでお間違いなきように。
サンプルコード
環境情報
- yarn: 1.22.4
- react: 16.13.1
- react-diff-viewer: 3.1.1
使い方
インストール
$ yarn add react-diff-viewer # or $ npm i react-diff-viewerサンプル実装
App.jsximport React, { PureComponent } from "react"; import ReactDiffViewer from "react-diff-viewer"; const oldCode = ` const a = 10 const b = 10 const c = () => console.log('foo') if(a > 10) { console.log('bar') } console.log('done') `; const newCode = ` const a = 10 const boo = 10 if(a === 10) { console.log('bar') } `; class Diff extends PureComponent { render = () => { return ( <ReactDiffViewer oldValue={oldCode} newValue={newCode} splitView={true} leftTitle={"oldCode"} rightTitle={"newCode"} /> ); }; } export default Diff;表示される画面
オプション
下記のサンプルコードを使用して、いくつかのオプションを紹介します。
App2.jsximport React, { PureComponent } from "react"; import ReactDiffViewer from "react-diff-viewer"; const oldText = ` # react-diff-viewer を使って GitHub 風の diff を表示する [react-diff-viewer](https://github.com/praneshr/react-diff-viewer) は React アプリケーションで GitHub 風の Diff を簡単に表示することできるライブラリです。 React.js で Diff を表示するライブラリは他にも、[react-diff-view](https://github.com/otakustay/react-diff-view) がありますが、こちらは react-diff-viewer に関する記事になりますのでお間違いなきように。 ## SampleCode [react-diff-viewer-sample](https://github.com/t0yohei/react-diff-viewer-sample) `; const newText = ` # react-diff-viewer を使って GitHub 風の diff を表示する [react-diff-viewer](https://github.com/praneshr/react-diff-viewer) は React アプリケーションで GitHub 風の Diff を簡単に表示することできるライブラリです。 [公式のデモはこちら](https://praneshravi.in/react-diff-viewer/)です。 React.js で Diff を表示するライブラリは他にも、[react-diff-view](https://github.com/otakustay/react-diff-view) がありますが、こちらは react-diff-viewer に関する記事になりますのでお間違いなきように。 ## サンプルコード [react-diff-viewer-sample](https://github.com/t0yohei/react-diff-viewer-sample) ## 環境情報 - yarn: 1.22.4 - react: 16.13.1 - react-diff-viewer: 3.1.1 `; class Diff extends PureComponent { render = () => { return ( <ReactDiffViewer oldValue={oldText} newValue={newText} splitView={false} disableWordDiff={true} hideLineNumbers={true} useDarkTheme={true} /> ); }; } export default Diff;表示される画面
オプションの説明
Prop 型 初期値 詳細 splitView boolean
true
unified
とsplit
の表示を切り替えます。disableWordDiff boolean
false
diff の中の単語 diff の表示・非表示を切り替えます。 hideLineNumbers boolean
false
行番号の表示・非表示を切り替えます。 useDarkTheme boolean
true
ダークモードの ON/OFF を切り替えます その他、詳細なオプションは下記をご参照ください。
https://github.com/praneshr/react-diff-viewer#props実装上の注意
UIkit v3.5.7 などをアプリケーション全体に適用している場合、
ReactDiffViewer
コンポーネント内のpre
タグのスタイルが UIkit などにより上書かれてしまい、react-diff-viewer
のスタイルが崩れる場合があります。
dirty hacking な回避方法としては、下記のような css ファイルを別途用意して、react-diff-viewer
を使用している jsx のファイル内で require してあげるなどがあります。style.scsspre { padding: 0px !important; border: none !important; border-radius: unset !important; background: inherit !important; }
- 投稿日:2020-09-14T00:21:28+09:00
【React.js】class構文 と fanction構文
前書き
Reactを学習していた中で "class構文・fanction構文" を学習しましたので、こちらでアウトプットとして記録いたします。
学習されている方にお役に立てると非常に嬉しいです。また、コードは Github で公開しているので気になるかたはダウンロードしてみてください。
class構文 と function構文とは
Reactをコーディングする方法として "class構文" と "fanction構文" があります。
これらの表記は↓になります。Class構文import React from 'react'; class 関数名 extends React.Component { render(){ return( <React.Fragment> 処理 </React.Fragment> ); } } export default 関数名;function構文import React from 'react'; function 関数名(引数) { return ( <div className="Comment"> 処理 </div> ); } export default 関数名;また、function構文にはもう1つ表記方法があります。
arrow関数import React from 'react'; const 関数名 = (引数) => { return( <> 処理 </> ) } export default 関数名;こちらは、ES2015(ES6)のアロー関数で表記されたものです。
どの構文で書けばいいのか?
業務環境により、構文使用の優先度は異なると思いますが、できるだけなら "function構文のアロー関数" で表記する方が良いです。
その理由は "class構文" よりも "function構文" の方が シンプル に表現できるため。
コーディングをする上では、複雑なコードを書くよりも、シンプルに表記される方が好ましいです。
また、Javascriptの使用は現在では "ES2015(ES6)" が推奨されます。アロー関数は ES2015 に該当するので使っていく方が良いでしょう。しかし、アロー関数 は全てのブラウザで表示可能な訳ではありません。
現在では大抵のブラウザは対応しますが、古い環境下だと対応していないのでこれは知識に入れましょう。(アロー関数の動作環境)
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functionsまた、次からは MAP配列を使った "class構文" と "function構文" のページを比較します。
class構文で書く
ここでは、横並びのコンテンツを "class構文" で書いてみます。
次に、function構文で同じ者を作るので、比較をしてみましょうClass構文(Language.js)import React from 'react'; class Language extends React.Component { // Übergeben "props" mit Daten als Argument render(){ return( <div className='language-item'> <div className="language-name">{this.props.name}</div> <img className='language-image' src={this.props.image} /> <div className="language-introduction">{this.props.introduction}</div> </div> ); } } export default Language;(行っていること)
データを持つpropsを引数に渡しています。
class構文だとこの処理に "this.props.image" など this を使うのが特徴的です。Class構文(Language.js)import React from 'react'; import Language from './Language' import './App.css'; class Main extends React.Component{ render(){ //Datenarray Definition (MAP) const languageList = [ { name: 'English', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_england.png', introduction: 'Diese Sprache wird vom Vereinigten Königreich und den Vereinigten Staaten gesprochen.' }, { name: 'Japanish', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_japan.png', introduction: 'Diese Sprache wird in Japan gesprochen.' }, { name: 'Deutsch', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_germany.png', introduction: 'Diese Sprache wird in Deutschland und der Schweiz gesprochen.' } ]; return( <div> <h1>Welche Sprache sprichst du?</h1> <div className='language'> {/* Datenarray aufrufen */} {languageList.map((languageItem)=> { return( <Language name = {languageItem.name} image = {languageItem.image} introduction = {languageItem.introduction} /> ) })} </div> </div> ); } } export default Main;(行っていること)
MAP配列を定義し、(MAPの)データ配列を呼び出しています。
アロー関数を使って (languageItem) => {return ‥} の中です。Class構文(index.js)import React from 'react'; import ReactDOM from 'react-dom'; import './App.css'; import Header from './Header'; import Footer from './Footer'; import Main from './Main'; import * as serviceWorker from './serviceWorker'; ReactDOM.render( <React.StrictMode> <Header /> <Main /> <Footer /> </React.StrictMode>, document.getElementById('root') ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();(行っていること)
個別のコンポネートを index.js に記しています。※こちらでは、cssや他コンポネートは記していません。下記のgithubでコーディングファイルを共有しているので、気になった方はダウンロードをして確認してみてください。
→Github
こちらでは、class構文のファイルをダウンロードできます。
(Githubでは、CSS・HTMLなど他データも含まれます)class構文では "this" や が特徴的です。
では、function構文(アロー関数)で書いてみます。
function構文(アロー関数)で書く
Function構文(Main.js)import React from 'react'; import Language from './Language' import './App.css'; const Main = (props) => { //Datenarray Definition (MAP) let languageList = [ { name: 'English', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_england.png', introduction: 'Diese Sprache wird vom Vereinigten Königreich und den Vereinigten Staaten gesprochen.' }, { name: 'Japanish', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_japan.png', introduction: 'Diese Sprache wird in Japan gesprochen.' }, { name: 'Deutsch', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_germany.png', introduction: 'Diese Sprache wird in Deutschland und der Schweiz gesprochen.' } ]; return( <> <h1>Welche Sprache sprichst du?</h1> <div className='language'> {/* Datenarray aufrufen */} {languageList.map((languageItem)=> { return( <Language name = {languageItem.name} image = {languageItem.image} introduction = {languageItem.introduction} /> ) })} </div> </> ) } export default Main;(行っていること)
MAP配列を定義し、(MAPの)データ配列を呼び出しています。
アロー関数を使って (languageItem) => {return ‥} の中です。Function構文(Language.js)import React from 'react'; const Language = (props) => { // Übergeben "props" mit Daten als Argument return( <div className='language-item'> <div className="language-name">{props.name}</div> <img className='language-image' src={props.image} /> <div className="language-introduction">{props.introduction}</div> </div> ) } export default Language;(行っていること)
データを持つpropsを引数に渡しています。
function構文だと this がないのが特徴的です。→Github
こちらでは、アロー関数とアロー関数ではないのファイルをダウンロードできます。
(Githubでは、CSS・HTMLなど他データも含まれます)以上が Class構文 と function構文 でした。
また下記は、function構文の注意点です。function構文の注意! "state" が使えない
Reactでの制作経験があると、多くの場合は "state" 処理をしています。
しかし、タイトルにある様に "function構文" では state が使えません。なので、どうしても state を使いたい場合は "class構文" が書く必要があります。しかし、先に述べた様に "function構文" を推奨しています。
では、 functionでstateを使用したい場合はどうすればいいのだろうか?
解決方法があります。それは "React hocks" を使用することです。あとがき
ここまで読んでいただき、ありがとうございました。
学習をしていて、class構文やfunction構文で悩んでいたので、こちらを学習しました。
まだまだ、Reactについては浅学ですが、学習を続けたいと思います。参考リンク
日本一わかりやすいReact入門#4 コンポーネント間でデータの受け渡しと再利用をしよう
Myリンク
また、Twitter・Portfolio のリンクがありますので、気になった方は
ぜひ繋がってください。プログラミング学習を共有できるフレンドが出来るととても嬉しいです。
- 投稿日:2020-09-14T00:21:28+09:00
【React.js】class構文 と function構文
前書き
Reactを学習していた中で "class構文・function構文" を学習しましたので、こちらでアウトプットとして記録いたします。
学習されている方にお役に立てると非常に嬉しいです。また、コードは Github で公開しているので気になるかたはダウンロードしてみてください。
class構文 と function構文とは
Reactをコーディングする方法として "class構文" と "fanction構文" があります。
これらの表記は↓になります。Class構文import React from 'react'; class 関数名 extends React.Component { render(){ return( <React.Fragment> 処理 </React.Fragment> ); } } export default 関数名;function構文import React from 'react'; function 関数名(引数) { return ( <div className="Comment"> 処理 </div> ); } export default 関数名;また、function構文にはもう1つ表記方法があります。
arrow関数import React from 'react'; const 関数名 = (引数) => { return( <> 処理 </> ) } export default 関数名;こちらは、ES2015(ES6)のアロー関数で表記されたものです。
どの構文で書けばいいのか?
業務環境により、構文使用の優先度は異なると思いますが、できるだけなら "function構文のアロー関数" で表記する方が良いです。
その理由は "class構文" よりも "function構文" の方が シンプル に表現できるため。
コーディングをする上では、複雑なコードを書くよりも、シンプルに表記される方が好ましいです。
また、Javascriptの使用は現在では "ES2015(ES6)" が推奨されます。アロー関数は ES2015 に該当するので使っていく方が良いでしょう。しかし、アロー関数 は全てのブラウザで表示可能な訳ではありません。
現在では大抵のブラウザは対応しますが、古い環境下だと対応していないのでこれは知識に入れましょう。(アロー関数の動作環境)
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functionsまた、次からは MAP配列を使った "class構文" と "function構文" のページを比較します。
class構文で書く
ここでは、横並びのコンテンツを "class構文" で書いてみます。
次に、function構文で同じ者を作るので、比較をしてみましょうClass構文(Language.js)import React from 'react'; class Language extends React.Component { // Übergeben "props" mit Daten als Argument render(){ return( <div className='language-item'> <div className="language-name">{this.props.name}</div> <img className='language-image' src={this.props.image} /> <div className="language-introduction">{this.props.introduction}</div> </div> ); } } export default Language;(行っていること)
データを持つpropsを引数に渡しています。
class構文だとこの処理に "this.props.image" など this を使うのが特徴的です。Class構文(Language.js)import React from 'react'; import Language from './Language' import './App.css'; class Main extends React.Component{ render(){ //Datenarray Definition (MAP) const languageList = [ { name: 'English', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_england.png', introduction: 'Diese Sprache wird vom Vereinigten Königreich und den Vereinigten Staaten gesprochen.' }, { name: 'Japanish', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_japan.png', introduction: 'Diese Sprache wird in Japan gesprochen.' }, { name: 'Deutsch', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_germany.png', introduction: 'Diese Sprache wird in Deutschland und der Schweiz gesprochen.' } ]; return( <div> <h1>Welche Sprache sprichst du?</h1> <div className='language'> {/* Datenarray aufrufen */} {languageList.map((languageItem)=> { return( <Language name = {languageItem.name} image = {languageItem.image} introduction = {languageItem.introduction} /> ) })} </div> </div> ); } } export default Main;(行っていること)
MAP配列を定義し、(MAPの)データ配列を呼び出しています。
アロー関数を使って (languageItem) => {return ‥} の中です。Class構文(index.js)import React from 'react'; import ReactDOM from 'react-dom'; import './App.css'; import Header from './Header'; import Footer from './Footer'; import Main from './Main'; import * as serviceWorker from './serviceWorker'; ReactDOM.render( <React.StrictMode> <Header /> <Main /> <Footer /> </React.StrictMode>, document.getElementById('root') ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();(行っていること)
個別のコンポネートを index.js に記しています。※こちらでは、cssや他コンポネートは記していません。下記のgithubでコーディングファイルを共有しているので、気になった方はダウンロードをして確認してみてください。
→Github
こちらでは、class構文のファイルをダウンロードできます。
(Githubでは、CSS・HTMLなど他データも含まれます)class構文では "this" や が特徴的です。
では、function構文(アロー関数)で書いてみます。
function構文(アロー関数)で書く
Function構文(Main.js)import React from 'react'; import Language from './Language' import './App.css'; const Main = (props) => { //Datenarray Definition (MAP) let languageList = [ { name: 'English', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_england.png', introduction: 'Diese Sprache wird vom Vereinigten Königreich und den Vereinigten Staaten gesprochen.' }, { name: 'Japanish', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_japan.png', introduction: 'Diese Sprache wird in Japan gesprochen.' }, { name: 'Deutsch', image: 'http://hudehisa.sakura.ne.jp/gitgub_image/react_flag_germany.png', introduction: 'Diese Sprache wird in Deutschland und der Schweiz gesprochen.' } ]; return( <> <h1>Welche Sprache sprichst du?</h1> <div className='language'> {/* Datenarray aufrufen */} {languageList.map((languageItem)=> { return( <Language name = {languageItem.name} image = {languageItem.image} introduction = {languageItem.introduction} /> ) })} </div> </> ) } export default Main;(行っていること)
MAP配列を定義し、(MAPの)データ配列を呼び出しています。
アロー関数を使って (languageItem) => {return ‥} の中です。Function構文(Language.js)import React from 'react'; const Language = (props) => { // Übergeben "props" mit Daten als Argument return( <div className='language-item'> <div className="language-name">{props.name}</div> <img className='language-image' src={props.image} /> <div className="language-introduction">{props.introduction}</div> </div> ) } export default Language;(行っていること)
データを持つpropsを引数に渡しています。
function構文だと this がないのが特徴的です。→Github
こちらでは、アロー関数とアロー関数ではないのファイルをダウンロードできます。
(Githubでは、CSS・HTMLなど他データも含まれます)以上が Class構文 と function構文 でした。
また下記は、function構文の注意点です。function構文の注意! "state" が使えない
Reactでの制作経験があると、多くの場合は "state" 処理をしています。
しかし、タイトルにある様に "function構文" では state が使えません。なので、どうしても state を使いたい場合は "class構文" が書く必要があります。しかし、先に述べた様に "function構文" を推奨しています。
では、 functionでstateを使用したい場合はどうすればいいのだろうか?
解決方法があります。それは "React hocks" を使用することです。あとがき
ここまで読んでいただき、ありがとうございました。
学習をしていて、class構文やfunction構文で悩んでいたので、こちらを学習しました。
まだまだ、Reactについては浅学ですが、学習を続けたいと思います。参考リンク
日本一わかりやすいReact入門#4 コンポーネント間でデータの受け渡しと再利用をしよう
Myリンク
また、Twitter・Portfolio のリンクがありますので、気になった方は
ぜひ繋がってください。プログラミング学習を共有できるフレンドが出来るととても嬉しいです。