- 投稿日:2021-03-01T22:55:38+09:00
JavaScriptを知っている方がTypeScriptをなんとなく理解するための記事① ~はじめに~
この記事は何?
TypeScriptとは何か、何がいいのかを伝えようと頑張った記事です!
この記事のターゲットは、以下のような方々です
- JavaScriptはわかったけど、TypeScriptってなんだっけ?
- TypeScriptというものがあるらしい...学んでみよう...!
この記事が読み終わったら、以下?の記事も是非!
- JavaScriptを知っている方がTypeScriptをなんとなく理解するための記事① ~はじめに~
←この記事
- TypeScriptをなんとなく理解するための記事② ~型を組み合わせる: Union~
- TypeScriptをなんとなく理解するための記事③ ~汎用的な型を作成する: Generics~
- TypeScriptをなんとなく理解するための記事④ ~構造型~
TypeScriptがなんとなく理解できたら、是非インストールして、触ってみてください!
→ 【TypeScriptを導入しよう!】エンジニアもすなるTypeScriptといふものを、我もしてみむとてするなり(3/3 作成予定)TypeScriptとは?
TypeScriptは、型定義ができるJavaScriptです。
JavaScriptでは、型を明確に宣言していません。
そこで、TypeScriptでは、この定数は数値型(number)として宣言!、あの定数は文字型(string)として宣言!
といったように型を宣言しつつJavaScriptを書いていくことができます。型定義によって、何がうれしいのかというと、
コードの予期しない動作によるバグを減らすことが出来ます例えば、以下のような場合です。
本当は、文字列として扱いたい定数が、なにかしらの処理によって、最終的に数値が入ってしまい、エラーが起きた。。。
TypeScriptを使えば「コーディング段階」でこのような型の矛盾を、検知することが出来ます。
型に関する概要
今回は、TypeScriptの基本的な機能である、1. 型推論、2. 型の定義について紹介します。
1. 型推論
型推論とは、何も型を定義しなくても、勝手に型を推論してくれる(型を生成してくれる)神の御業です。
たとえば、以下のようなコードを書いたとします。let smartPhone = 'Android';そして、この変数に数値を入れてみましょう。
let smartPhone = 'Android'; smartPhone = 11; // Problem: タイプ「数値」はタイプ「文字列」に割り当てることができません.ts(2322)すると、数値を代入した行で「タイプ「数値」はタイプ「文字列」に割り当てることができません.ts(2322)」と警告されました。
つまり、最初に'Android'
を代入した時点で、TypeScriptが自動的に型を推論し、割り当てるので、
このsmartPhone
変数には文字列(string)以外を代入しようとすると、怒られてしまいます。これが、型推論になります。
このように自動的に推論してくれるので、引数が文字列でないと駄目?な関数に誤って、数値を入れることもなくなります。
「引数は、文字列でないと駄目です!この変数は数値型です!」と勝手に怒ってくれるわけです。let version = 11; // 数値(number)型 const upVersion = (device: string) => { // 引数は文字列(string)型 console.log(`OSは${device}です`) } upVersion(version); // Problem: タイプ 'number'の引数をタイプ 'string'のパラメーターに割り当てることはできません。ts(2345)2. 型の定義
型定義とは、字の通り型を(明示的に)定義することです。
簡単な例は、以下になります。let version: number = 11; // versionは数値(number)型ですよ! const smartPhone: string = 'Android'; // smartPhoneは文字列(string)型ですよ!JavaScriptでは、様々なデザインパターンを利用てきますが、一部のデザインパターンでは、型を自動的に推測することは困難です。
例えば、以下のようなObjectです。const fish = { name: "iwana", weight: 100, }これは、
interface
宣言を利用すると、事前にオブジェクトの形状を定義することが出来ます。
今回は動物である、Animal
型を作ってみました。interface Animal { name : string; weight: number; }この
Animal
型は次のように利用します。const penguin: Animal = { name: "Emperor penguin", weight: 10000, }仮に、Animal型と一致しないオブジェクトを指定すると、警告が出ます。
const plastic: Animal = { name: "pen", material: "oil", // オブジェクトリテラルは既知のプロパティのみを指定でき、「material」はタイプ「Animal」に存在しません。ts(2322) weight: 5, }また、クラスとオブジェクト指向プログラミングのサポート、関数の引数の型や返り値の型もサポートしています。
// Animal型 interface Animal { name: string; weight: number; } // class class AnimalBook { name: string; weight: number; constructor(name: string, weight: number) { this.name = name; this.weight = weight; } } const user: AnimalBook = new AnimalBook("dog", 1000); // 関数の返り値をAnimal型に const getAnimalInfo = (): Animal => { return { name: "Emperor penguin", weight: 10000, }; }; // 関数の引数をAnimal型に const deleteAnimalInfo = (animal: Animal):void => { ///... }他にも、JavaScriptの
boolean
、bigint
、null
、symbol
、object
、undefined
なども利用できます。
加えて、TypeScript特有のany
型やunknown
型、never
やvoid
もあります。ちなみに今回は、
interface
を利用して、型をカスタマイズしましたが、Type
という構文を使って、型を作る事もできます。おわりに
以上が、TypeScriptで重要な1. 型推論と2. 型定義でした!
基本的に概要なので深くまで説明していませんが、TypeSciptについて理解が進めば幸いです。わかりやすい!と思った方は是非LGTM✨おねがいします
Next: TypeScriptをなんとなく理解するための記事② ~型を組み合わせる: Union~
参考文献
- 投稿日:2021-03-01T22:55:38+09:00
JavaScriptを知っている方がTypeScriptをなんとなく理解するための記事 ~はじめに~
この記事は何?
TypeScriptとは何か、何がいいのかを伝えようと頑張った記事です!
この記事のターゲットは、以下のような方々です
- JavaScriptはわかったけど、TypeScriptってなんだっけ?
- TypeScriptというものがあるらしい...学んでみよう...!今日から数日にわたって記事を書く予定なので、この記事が読み終わった方は、以下も是非お読みください。
・ TypeScriptをなんとなく理解する ~型を組み合わせる~ (3/2更新予定)
・ TypeScriptをなんとなく理解する ~ジェネリック型~ (3/2更新予定)
・ TypeScriptをなんとなく理解する ~構造型~ (3/3更新予定)※ もし誤りや改善点があればコメントで教えて下さい!
TypeScriptとは?
TypeScriptは、型定義ができるJavaScriptです。
JavaScriptでは、型を明確に宣言していません。
そこで、TypeScriptでは、この定数は数値型(number)として宣言!、あの定数は文字型(string)として宣言!
といったように型を宣言しつつJavaScriptを書いていくことができます。型定義によって、何がうれしいのかというと、
コードの予期しない動作によるバグを減らすことが出来ます例えば、以下のような場合です。
本当は、文字列として扱いたい定数が、なにかしらの処理によって、最終的に数値が入ってしまい、エラーが起きた。。。
TypeScriptを使えば「コーディング段階」でこのような型の矛盾を、検知することが出来ます。
型に関する概要
今回は、TypeScriptの基本的な機能である、1. 型推論、2. 型の定義について紹介します。
1. 型推論
型推論とは、何も型を定義しなくても、勝手に型を推論してくれる(型を生成してくれる)神の御業です。
たとえば、以下のようなコードを書いたとします。let smartPhone = 'Android';そして、この変数に数値を入れてみましょう。
let smartPhone = 'Android'; smartPhone = 11; // Problem: タイプ「数値」はタイプ「文字列」に割り当てることができません.ts(2322)すると、数値を代入した行で「タイプ「数値」はタイプ「文字列」に割り当てることができません.ts(2322)」と警告されました。
つまり、最初に'Android'
を代入した時点で、TypeScriptが自動的に型を推論し、割り当てるので、
このsmartPhone
変数には文字列(string)以外を代入しようとすると、怒られてしまいます。これが、型推論になります。
このように自動的に推論してくれるので、引数が文字列でないと駄目?な関数に誤って、数値を入れることもなくなります。
「引数は、文字列でないと駄目です!この変数は数値型です!」と勝手に怒ってくれるわけです。let version = 11; // 数値(number)型 const upVersion = (device: string) => { // 引数は文字列(string)型 console.log(`OSは${device}です`) } upVersion(version); // Problem: タイプ 'number'の引数をタイプ 'string'のパラメーターに割り当てることはできません。ts(2345)2. 型の定義
型定義とは、字の通り型を(明示的に)定義することです。
簡単な例は、以下になります。let version: number = 11; // versionは数値(number)型ですよ! const smartPhone: string = 'Android'; // smartPhoneは文字列(string)型ですよ!JavaScriptでは、様々なデザインパターンを利用てきますが、一部のデザインパターンでは、型を自動的に推測することは困難です。
例えば、以下のようなObjectです。const fish = { name: "iwana", weight: 100, }これは、
interface
宣言を利用すると、事前にオブジェクトの形状を定義することが出来ます。
今回は動物である、Animal
型を作ってみました。interface Animal { name : string; weight: number; }この
Animal
型は次のように利用します。const penguin: Animal = { name: "Emperor penguin", weight: 10000, }仮に、Animal型と一致しないオブジェクトを指定すると、警告が出ます。
const plastic: Animal = { name: "pen", material: "oil", // オブジェクトリテラルは既知のプロパティのみを指定でき、「material」はタイプ「Animal」に存在しません。ts(2322) weight: 5, }また、クラスとオブジェクト指向プログラミングのサポート、関数の引数の型や返り値の型もサポートしています。
// Animal型 interface Animal { name: string; weight: number; } // class class AnimalBook { name: string; weight: number; constructor(name: string, weight: number) { this.name = name; this.weight = weight; } } const user: AnimalBook = new AnimalBook("dog", 1000); // 関数の返り値をAnimal型に const getAnimalInfo = (): Animal => { return { name: "Emperor penguin", weight: 10000, }; }; // 関数の引数をAnimal型に const deleteAnimalInfo = (animal: Animal):void => { ///... }他にも、JavaScriptの
boolean
、bigint
、null
、symbol
、object
、undefined
なども利用できます。
加えて、TypeScript特有のany
型やunknown
型、never
やvoid
もあります。ちなみに今回は、
interface
を利用して、型をカスタマイズしましたが、Type
という構文を使って、型を作る事もできます。おわりに
以上が、TypeScriptで重要な1. 型推論と2. 型定義でした!
基本的に概要なので深くまで説明していませんが、TypeSciptについて理解が進めば幸いです。参考文献
- 投稿日:2021-03-01T22:43:02+09:00
未経験からweb系自社開発企業内定までの過程の築き方と今後のキャリア形成
この記事を書くにあたり
今私は契約社員ではあるが、
ベンチャー企業にて開発部門にて戦力になるべく奮闘中。
少し客観的な視点でここまでの道のりと今後の目標などを踏まえ、
反省点なども含め時系列で整理していこうと思う。
また、未経験スキルでの転職のリアル感が伝わればどんな感じで転職の道が進んでいくのか、
よりわかりやすいと思うのでその辺も書いていきたいと思う。簡単な経歴
高校を卒業してインフラ系の会社に入社。
- 数年間、機械や装置を扱うオペレーターを担当、簡単なシーケンスなども作成。
1社目のインフラ系の会社を辞める半年前にプログラミングスクールに入校。
- 選択した言語はJavaとSwift。
空白期間を経て、コールセンターへ入社。
- 担当はテクニカルサポート。
SES会社へ入社。
- 緊急事態宣言の影響でどこへもアサインできず社内待機を過ごす。
コールセンターへ入社。
- 経験を生かしてテクニカルサポートを担当。
テスター求人を見てベンチャー企業へ入社。
- 現在に至る。
全くの未経験期間
プログラミングスクールを探すまで
今でこそ、転職のノウハウは良い意味でも悪い意味でも慣れた物だが、まず、10年もいた会社から転職するということが未知の世界であったため、何をして良いか分からない状態であった。
電車の中吊りで転職サイトの広告を見て気になるなと思う程度でその先はどうなっているのかすらわからないって感じ。
なので、転職について色々とググってみたりYouTubeを見たりしたものだった。この状態では正しい情報を見つけ出すのって相当難しい。
少し端折るが、そんなこともありパソコンのスキルが相当落ちていたと実感し、先ずはスクールを探した。
結局は実際に校舎がある老舗のスクールへ入校した。
結果的には、当時の自分にとっては問題ない入校だった。
なぜなら、当時は分からなかったがパソコンのスペックもエンジニアが持つ物ではなかったので結果的によかったと思う。
その程度の知識であったのだった。入校後の受講プログラム
当時受講したのが、JavaとSwift。
正確に言えばAndroidとiPhoneアプリ作成コース。
なぜこのコースを選んだかといえば、単純にアプリを作ってみたかったからということと、
メジャーな言語であるJavaも習うことができるということ。
結果的にこのコースを選んだのは少し遠回りだった気もした。
Web制作コースやPHP、JSなどの言語を選んでおけばとも後々思ったりもしたが、
今の仕事をしている段階では全く役に立たないとも思ってはいない。
幅広い視点を持つことは全然問題ないことでもあるし、
情報系などの大学も出ていない私にとってJavaは言語の基礎を教えてくれたと言っても過言ではないだろう。
その後で、自分で調べて学べば良いという思考になったので、あとは何も問題ない。
話を戻すと、Javaを中心に受講させてもらい、オマケ程度にアプリ作成といった感じで半年ほどで受講を修了した。
コンパイルとは何か。
2進数、16進数、、、
機械語とは。
などなど
少しアカデミックなことを触れてコーディングに入っていき、
演習問題の繰り返しだった。初めての転職フェア
そんなこんなで1社目はさっさと辞めてしまわないと辞めづらく、精神的にももたないので、
転職ができなくても辞めるつもりでいた。
とはいえのんびり転職を待つのもよくないので、
先ずは転職フェアに参加してみることにした。
知っている人なら知っている転職フェア。
あれはいわゆるSESフェア。
まあ、わかるとは思うが行かない方が良い。
分からない人にとってはIT業界ってああいうところなんだと洗脳されかける。面接を受けてみたり、エントリーをしてみるがが上手くいかない。
コールセンター(テクサポ)へ
そんなこんなで仕事をしないのもよくないので、
コールセンターへ流れ着く。
転職後はほとんどをコールセンターで過ごすことになる。朝活でPHP
コールセンターにずっといるわけにもいかないので、
朝の喫茶店で毎日就業前にPHPの勉強をすることにした。緊急事態宣言を抜けてのベンチャーへ
色々あってコールセンターを行き来するのだが、
ようやくベンチャーでテスター業務から携わることになるわけだった。
それができたのも、
結局はReactでFirebaseにデプロイまで行けた知識を持てたということ。
コードを書いているだけでは話が薄っぺらくなってしまう。
そして、入社して思うのは実務経験に勝るものはないということ。
お金を貰いながらその業務に専念することでのスキルアップは格段に違う。
ようやく、ポジションに来れたのだから、
コーディングだけでなく、テストケースの作成、サーバー、インフラ側の知識、RDBやAPIのことなど、
いままで自分だけでは時間を割くことができなかったことにもやっていくことができるのではないだろうか。
周囲の優秀なエンジニアに囲まれて仕事ができることがいかに幸せなことか、
昨今の転職の大変さを聞いてよく身に染みる。今も少しずつコーディングをしているが、
EC2ぐらいを使って繋げられたらと思っている。JenkinsやCircleciを使って自動テストの知識についても増やしていきたい。
AWSを学ぶのならDockerもやりたいわけだ。学ぶことは多い。
フロントの勉強をしていると、
限界を感じることが多く、
向上心があればどうしてもインフラ周りにいきたくなる。
なるほど、フロント側にフルスタックが多いのも納得と思った今日この頃。
- 投稿日:2021-03-01T22:02:29+09:00
ASP.net coreの探索 ~3 ReactでSPAを作ってみた~
1 RazorによるMVCアプリケーション
2 CRUDページとRazorを見る
3 ReactでSPAを作ってみた ←今回今回のテーマ
今回はReact.jsを用いてSPA(シングルページアプリケーション)を
作ってみます。
ASP.net coreでSPAを作成する場合、普通はBlazorを使うのだと思われますが
プロジェクト作成すると「React.js」があったので、
折角だから使ってみようと思いました。今回はこんなものを作ってみます。
非常に簡単なWebアプリを作ってみたい!って人がいたら
いつもおみくじアプリを薦めてます。
JavaScriptによるおみくじ表示と
引いた人リストによるバックエンドとのやりとりで
Webアプリの練習になるかなーと思ってます。ちなみに普段SPA作る際は、Vue.jsを使用しているので
今回このためにReactを学びました。
そのため、よくわかってない付け焼き刃なReactを書いているので、
色々間違ってたり、あり得ないソースコードになってると思います...
(プロジェクト作成にはAngularもあるのに、なぜかVueは無かった...)Reactプロジェクトの作成
いつものようにVisual Studioを用いてプロジェクトを作成しましょう。
ASP.net core webアプリケーションを作成し
React.jsを選択します。
React内で大掛かりなデータやりとりがないとされるため
今回はReact.jsで行います。(Reduxは使いません。)プロジェクトが出来たところで、サンプルページを開いてみましょう。
初回実行少々時間がかかります。
(npmが動いでたようなので、環境をインストールしてるのかな?)・ASP.net coreとC#
・React
・Bootstrap
を使用してます!ってメッセージが出ます。画面上のナビゲーションバー(ヘッダー)に
いくつか項目がありますね。
[Counter]を押したら、ボタンカウンターが出ました。
5回押したら5カウントされました。
[Fetch Data]を押したら、天気予報?が出ました。
5日間とも同じ時刻なのに、気温が偉く変わってますね-
-9℃の2日後に39℃になるって、どんな地域なんでしょうか?笑JSファイルを編集しておみくじを作る
Reactのファイルを編集して、おみくじを作っていきます。
プロジェクトを作成した際のファイル構成は下記の通り
srcフォルダの中にjsファイルが入っています。
メイン画面の「App.js」と、componentフォルダにコンポーネントファイルが入ってますね。
(Omikuji.jsは後から作ったファイルです。)メイン画面の「App.js」の中身を見てみましょう。
App.jsimport React, { Component } from 'react'; import { Route } from 'react-router'; import { Layout } from './components/Layout'; import { Home } from './components/Home'; import { FetchData } from './components/FetchData'; import { Counter } from './components/Counter'; import './custom.css' export default class App extends Component { static displayName = App.name; render () { return ( <Layout> <Route exact path='/' component={Home} /> <Route path='/counter' component={Counter} /> <Route path='/fetch-data' component={FetchData} /> </Layout> ); } }コンポーネントをインポートして、ルーティングで表示をわけていますね。
今回はルートディレクトリの{Home}コンポーネントをおみくじにしてみましょう。
Home.jsimport React, { Component } from 'react'; import './NavMenu.css'; let fortune = ["Daikichi", "Chukichi", "Kichi", "Shokichi", "Suekichi", "Kyo", "Daikyo"]; //運勢リスト export class Home extends Component { constructor(props) { super(props); //propsを継承 this.state = { // this.state message: "Please draw Omikuji !!", //初期メッセージ displayName: "", //引いた人の名前 index:0, //運勢インデックス } this.drawOmikuji = this.drawOmikuji.bind(this); //メソッドをクラスにバインド this.changeName = this.changeName.bind(this); //メソッドをクラスにバインド } drawOmikuji(e) { //おみくじを引くメソッド this.setState(state => ({ //stateの変更 index: Math.floor(Math.random() * fortune.length), //ランダムで運勢インデックスを作成 message: this.state.displayName + "'s fortune is " + fortune[this.state.index]//メッセージを変更 })); } changeName(e) { //名前入力したら名前を取得 this.setState({ displayName: e.target.value }); //名前入力されたらstateのdisplayNameに名前を入れる } render () { return ( <div> <h1>Hello, Omikuji!</h1> <div className="omikujiPadding row"> <input type="text" className="form-control col-6" placeholder="Your name" onChange={this.changeName} /> <input type="submit" className="btn btn-primary col-3" value="Draw Omikuji" onClick={this.drawOmikuji} /> </div> <h2 className="messageStyle">{this.state.message}</h2> </div> ); } }画面のようにおみくじを実装しました。
運勢をリストにして、おみくじを引くときにランダムで
運勢リストから運勢を取り出します。Reactの仕様?なのか、配列はclassの外で作らないと使えないですね。
はじめはclassの中に「static fortune=[]」と入れましたが、
Uncaught TypeError: Cannot read property 'length' of undefined
が表示されて使えませんでした。
名前をGeorgeにして、「Draw Omikuji」でおみくじを引くと
メッセージが「Georgeの運勢は 吉」と出ました。
ちなみに日本語だとエンコードの関係で文字化けたため、英語にしてあります。引いた人リスト
実際のおみくじは、大凶が出るとおみくじを枝に結んで返しますね。
そのように、引いたら返すつもりで、引いた報告をする機能をつけてみます。
上イメージ図のように、引いた人の記録がテーブルに並ぶ感じにします。ここで、データを記録したり表示することが発生するため、バックエンドとの通信が必要になります。
ReactとASP.NET coreはどのようにしているのか?を探してみたところ
FetchData.js(天気予報コンポーネント)にヒントがありました。FetchData.jsasync populateWeatherData() { const response = await fetch('weatherforecast'); const data = await response.json(); this.setState({ forecasts: data, loading: false });ルート「weatherforecast」にfetchして
そこからjsonで天気データを受け取っているようです。
ファイルを色々調べてみると、「Controller」の中に「WeatherForecastController.cs」という
天気データをReactに送るコントローラが見つかりました。
つまり、リクエストに対してjsonを返す Web APIになっているのだと思われます。ということで、引いた人一覧クラスとそのコントローラーを作って
おみくじ返納Web APIを実装していきたいと思います。DrawedList.csusing System; namespace ReactOmikuji { public class DrawedList { public int ID { get; set; } //スキャフォールディング作成時の慣例 public string Name { get; set; } public string Fortune { get; set; } public DateTime Date { get; set; } } }引いた人一覧クラス「DrawedList」を作成します。
次に、「Controller」フォルダを右クリックし
「追加」→「コントローラ」→「API \ EFを使用したアクションがあるAPIコントローラ」
でコントローラを作成します。
Razorのスキャフォールディングと同じ要領で、コントローラを作成します。
コントローラにアクセスしたらAPIが動くように、Routeの中を書き換えます。DrawedListController.cs[Route("drawedlist")] [ApiController] public class DrawedListsController : ControllerBase{ private static readonly string[] NameSample = new[] //リストに載せる名前サンプル { "A", "B", "C" }; private static readonly string[] FortuneSample = new[] //リストに載せる運勢サンプル { "Daikichi", "Kichi", "Daikyo" }; private readonly ReactOmikujiContext _context; //コントローラー使用するためのオブジェクト public DrawedListsController(ReactOmikujiContext context) //コントローラ使用するためオブジェクトを処理 { _context = context; } // GET: DrawedList [HttpGet] public IEnumerable<DrawedList> Get() //DrawedListにアクセスした際の処理 { return Enumerable.Range(0,3).Select(index => new DrawedList //名前・運勢・引いた日付を { Date = DateTime.Now.AddDays(index), Fortune = FortuneSample[index], Name = NameSample[index] }) .ToArray(); //配列で返す } }「drawedlist」にアクセスすれば、Web APIが使えるようになりました。
今回は、「drawedlist」に行くと引いた人リストがjsonで返るようになってます。
SQL Serverは使用せず、いつも同じデータが出るようになってます。
(途中からSQL Serverがおかしくなり、使えなくなってしまった...)
jsonが出力されているのが確認できました。
これを受け取り、表にするコンポーネントを作ってみましょう。DrawedList.jsimport React, { Component } from 'react'; export class DrawedList extends Component { constructor(props) { super(props); this.state = { drawedlist: [], loading: true }; } componentDidMount() { //コンポーネント起動時にする処理 this.populateDrawedList(); //jsonデータをstateに入れる処理 } static renderListTable(drawedlist) { //引いた人リストをテーブルに表示するhtml return ( <table className='table table-striped' aria-labelledby="tabelLabel"> <thead> <tr> <th>Name</th> <th>Fortune</th> <th>Date</th> </tr> </thead> <tbody> {drawedlist.map(drawedlist => <tr key={drawedlist.id}> <td>{drawedlist.name}</td> <td>{drawedlist.fortune}</td> <td>{drawedlist.date}</td> </tr> )} </tbody> </table> ); } render() { //レンダー let contents = this.state.loading //表示させる中身オブジェクト ? <p><em>Loading...</em></p> //読み込みに時間がかかると Loadingと表示 : DrawedList.renderListTable(this.state.drawedlist); //読み込めたら表を表示 return ( <div> <p>This component demonstrates fetching data from the server.</p> {contents} </div> ); } async populateDrawedList() { //バックエンドと通信して、引いた人リストを取得 const response = await fetch('drawedlist'); //drawedlistにアクセス const data = await response.json(); //jsonデータを取得 this.setState({ drawedlist: data, loading: false }); //jsonデータをstateに入れる } }結構長くなってしまいましたが、テンプレートにある天気予報取得の
「FetchData.js」をそのまんま真似しただけです。起動時にFetchでDBに接続し、データを取得
↓
データをstateに入れる
↓
stateをmapで全部表示されるとやって表示させているだけですね。
最後にHome.jsに
<DrawedList />
を入れたら
引いた人リストが表示されました。ただし、現在は表示だけで
おみくじを引いたら新しく追加される機能はまだついていません。
SQL ServerやMySQLとの通信が出来たら、また挑戦してみようと思います。まとめ
長くなってしまいましたが、おみくじを一応作ってみた。
React.jsとASP.NET Coreでアプリを作ってみて感じたことは
・おみくじであればFirebaseでよい(ASP.NET Coreの必要がない)
・ASP.NET Coreのアドバンテージは、独自のWeb APIを作る場合
・Reactは(Vueと比べて)Javascript感がある
といったところでしょうか。初めて触ったReactですが、Javascriptを触っている感じがして
個人的にはVueよりも楽しめた気がします。
それから、ASP.NET CoreでSQL Serverと通信する場合は
Entity Frameworkというのを使うみたいです。
このEntity Frameworkを使いこなせば、MySQLが使えるのかなーと思います。
いずれチャレンジしてみたいです。次回はBlazorを使ってSPAを作ってみたいと思います。
参考文献
https://docs.microsoft.com/ja-jp/aspnet/core/client-side/spa/react?view=aspnetcore-5.0&tabs=visual-studio
Microsoftの公式ドキュメントです。https://ja.reactjs.org/
https://www.shuwasystem.co.jp/book/9784798056920.html
React.jsの公式ドキュメントと
書籍「React.js & Next.js超入門」です。
この2つを見ながらReactを実装しました。https://github.com/Sho-Zhao/ReactOmikuji.git
Githubに載せています。
- 投稿日:2021-03-01T19:22:21+09:00
自分の母校の授業で使われた謎解きゲームが公開終了したので色々振り返る
注意 これは2020年に限定公開で書いた記事ですが、2021/10/14に全体公開にしました。 もうプレイは出来ません。 はじめに 今まで業務でVueやAngularしか触ってきませんでしたが、漠然とReactを経験してみたいと思っていた所、タイミングよく誘われたので案件を手伝いました。 https://uminazo.jp/ それがなんと年末に母校の海洋問題の授業で使われました。 https://social-innovation-news.jp/?p=1176 2月末で公開が終わったので、React未経験からこのプロジェクトを通して学んだ技術的な知見をまとめていきます。 ※クライアント側の許可を貰って、確認頂いた上で当記事は投稿しています。 uminazoとは 日本財団が推進する「海と日本プロジェクト」の一環で作られた「海洋問題」について学べる謎解きゲームです。 中身はそこそこ難しく、自分はある程度の謎を知っているにも関わらず、クリアするのに1hほど時間がかかりました。 ※すでに公開は終わっているのでプレイは出来ません。 携わった事 1人がメインで動いていて、ノベル部分や全体の設計など大方の事はその方が行なってくれました。 自分はその方にレビューを貰いながら、個別に謎の実装に携わりました。 個別謎として1つ例を出すとパズル謎です。 パズル謎の実装 右側にあるピースがクリックにより90度回転し、真ん中のマス目にはめ込むことでパズルを解くことが出来ます。 ピース1つ1つに正解座標と正解回転度数を仕込んで、近くまでドラッグしたらピタッとハマる仕様になっています。 ドラッグにはreact-draggableを使いました。 クリックによる回転と合わせてこちらの記事で詳細は解説しています。 react-draggableにクリックイベントを追加する uminazoを通して得た学び あるあるじゃない機能作り 今までは業務システムのフロント開発をメインで行なってきました。 新しい画面の作成、機能の追加、バックエンドからのAPIの繋ぎ込みや、ライブラリの導入、バグ修正などです。 見たことある機能が多く、経験したことがなくてもググると類似の機能に関する情報が見つかりやすいものでした。 ですので、サーバー側の人との適切な連携、ドキュメントをしっかり読む力、などが養われていたかなーと感じていました。 しかし、今回作成したのはブラウザゲームで、ブラウザ上でゲーム性を表現しなくては行けません。 それぞれの謎が実装のイメージが湧きにくいし、ググっても近しい情報はない事が多かったです。 ですので、正攻法でそもそも実装できるのか? 難しいならどうすればゲームとして成立する形で実装できるか? みたいな所に頭を悩ませました。 詳細設計が綺麗に立たない分、「ユーザーにどの様に使われたいか?」という部分を常に頭に置いて実装を行う事ができ、、良い開発体験が積めたかなと思っています。 スマホ対応可能のブラウザゲーム スマホ対応も兼ねました。 静的なページのスマホ対応は普段行なっていますが、ゲームでは特殊なイベント操作が多く、スマホデバイス上でそれらを実現するのに苦労しました。 例えば、先ほど上げたパズル謎の例では、ドラッグイベント発火時にクリックイベントも同時に発火してしまうので、useStateでフラグを作り同時発火を防ぐ対処をしました。 photoshopの使用 今までもフロントエンドの業務ではコーディングの指標としてXDやskech、figma、zeplinを使ってきました。 しかし今回はphotoshopではコーディングの指標としてだけではなく、パーツを簡単に加工し切り抜くなどのちょっとした操作まで行いました。 制作の最終盤はデザイン担当の人に作り直して貰う時間もなかったので、要件を満たせるレベルでのデザイン修正なども経験できました。 Reactが実務で使えるレベルになった 2020年6月ごろに興味本位で触り始めたReactですが、2021年の年明けからはReact中心に仕事を行なっています。 理由として - uminazoでモダンなReactでの開発を経験し、自信がついた - 「りあくと」を読み、Reactの周辺知識が理解できて、Reactの背景的な魅力にハマった。 - uminazoをやる傍ら、簡単アプリを作成し技術的な基礎が固まった(connect4、買い物リスト、COVID-19トラッカー、Netflixのクローン) まとめ ここ最近はtoB系の業務システムの開発が多く、自分の技術的な成長にエンジニアリングの喜びを感じていました。 しかし、今回は運よく自分が携わったサービスが母校で使われた事で、「世の中に役に立つ物を作る」というエンジニアリングの根底にある喜びを再確認できました。 今年の4月でプログラミングを始めて3年になりますが、今後のキャリアの中で「技術的に成長」「世の中への貢献」の両輪をどう追い求めていくのか。考えるきっかけになりました。
- 投稿日:2021-03-01T16:43:06+09:00
お猿さんのためのReactまとめ:Vol.1
猿というか自分自身の為のまとめです。
Reactを学習していく中で、「あれ?これはなんだったっけ?」的な事をまとめて行きたいと思います。
また、Qiitaの書き方に慣れる意味もあります。
恐れずに言うのであれば、「アルジャーノンに花束を」のようにどんどん書くレベルが上がることを目指します。(勿論、物語の途中までで良いですが・・・。)1...最もシンプルな表示例
親コンポーネント、子コンポーネントともにreturnしたい要素は<div>
で囲む。
2...propsで要素を親から子に渡す。
3...propsで渡せる値の型
4...stateについて
stateとは?
- コンポーネント内で管理する変数(=ローカルステート) <-->グローバルステート
- propsとして子コンポーネントに渡せる。
なぜstateを使うのか?
- render()では値を変更してはいけない。
- 値の変更にがsetState()を使う。
- stateの変更は再レンダーのきっかけになるのでrender()内で行うと無限ループになってしまう。
- 設定はクラスコンポーネントが前提。
- constructor()内でオブジェクト型で記述する。
Blog.jsxclass Blog extends React.Component { //コンストラクター内で記述 constructor(props) { super(props); //オブジェクト型で記述 カッコは波カッコ{} this.state = { isPublished: false } } render() { return ( <div> <Article title='React' //このように記述することで同じコンポーネント内は参照できる。 isPublished={this.state.isPublished} /> </div> ) }; }; export default Blog;Article.jsxconst Article =(props)=> { return ( <> <h2>{props.title}</h2> <label htmlFor="check">stateの状態</label> <input type='checkbox' //子コンポーネントはこのように受け取る。 checked={props.isPublished} id='check' /> </> ) }; export default Article;stateを変更する
- setState()を使い、その中に記述されたstateのみ変更する。
- 関数にラップする。
- 投稿日:2021-03-01T16:32:37+09:00
毎日投稿(ReactとTypescriptでTodoアプリ改修)
本日はReactとTypescriptで作ったTodoアプリの改善をしました。
ToDoアプリは以下で学習しながら作りました。
【世界で7万人が受講】Understanding TypeScript - 2020年最新版
https://www.udemy.com/course/understanding-typescript-jp/このアプリを作り終えたときは、
以下の修正が必要だなと思いました。
1. 新しくTodo追加時にinputfromにそのTodoのテキストが残留してしまう。
2. 空欄でもTodoとして追加されてしまう。3〜5時間考えて、、、
以下のとおりコードを足し、2点とも改修できましたが、、
(本質的には考えると2番目は解決できていません。)const enteredText = textInputRef.current!.value; if(enteredText !== "") { onAddHandler(enteredText); textInputRef.current!.value = ''; } else { alert('入力してください'); }満足出来ていません。
バリデーションを使えばいいかなと思い、実装していたのですが、、途中で諦めました。。。
まだまだこれからも、TypeScriptもReactも勉強していきます。
追加機能しようと考えているので、できたら、またQiitaに書います!以下、githubに公開しています。
ありがとうございました。
- 投稿日:2021-03-01T14:15:12+09:00
【React】関数コンポーネントとクラスコンポーネント
関数コンポーネント(Function Components)
- TypeScriptでは関数コンポーネントの型は
React.FunctionComponent
インタフェースとして定義されている
-> エイリアスとして定義されているReact.FC
を使用可能/components/Hello.tsximport * as React from 'react'; // Hello コンポーネントの定義 export const Hello: React.FC = () => { return <h1>Hello</h1> };index.tsximport * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Hello } from './components/Hello'; ReactDOM.render(<Hello />, document.getElementById('root'));クラスコンポーネント(Class Components)
- TypeScriptでは
React.Component
を継承し、render()
メソッドを実装する/components/Hello.tsximport * as React from 'react'; export class Hello extends React.Component<Props> { public render(): JSX.Element { return <h1>Hello</h1> } };index.tsximport * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Hello } from './components/Hello'; ReactDOM.render(<Hello />, document.getElementById('root'));関数コンポーネントとクラスコンポーネントの違い
state(状態管理)とLifecycle methodを使用可能か
Hooks導入以前 Hooks導入後 クラスコンポーネント 使用可能 使用可能 関数コンポーネント 使用不可 使用可能 関数コンポーネントとクラスコンポーネントのどちらを使用するべきか
結論
- 関数コンポーネントを推奨
理由
- コードを簡潔に書けるため
this
を使う必要がなくなるconstructor
render
が不要になる- 同一ロジックが混入しにくいため
- ライフサイクルメソッドに分割する必要がない
- 投稿日:2021-03-01T12:27:01+09:00
useStateの使い方
概要
先日、React Hooksの学習を行いました。
今回は、useStateの使い方を紹介します。目次
- 事前知識
- Hookを使用するメリット
- useStateの使い方
- useStateの実用例
- 最後に...
事前知識
Reactには、関数コンポーネント(関数型で定義されたコンポーネント)とクラスコンポーネント(クラス型で定義されたコンポーネント)があります。
クラスコンポーネントでは、関数コンポーネントとは異なり、state(状態管理)やライフサイクルメソッドを使用する事が出来ます。Hookを使用するメリット
Hookを使用する事で、クラス機能(stateやライフサイクルメソッド)を関数コンポーネントでも使える様になります。
これにより、コードを簡潔に書け、可視性が上がりました。補足
・旧Reactの記述方法で開発を進めており、途中にReact Hooksを使用しても、これまでの記述に悪影響を出さないというのもメリットの一つです。useStateの使い方
まずは、useState関数をインポートします。
useState関数をインポートimport React, { useState } form 'react';次に、下記のコードでuseState関数を定義します。
useState関数を定義const [stateの変数名, stateを変更させる関数名] = useState(stateの初期値);最後に、stateを変更させる関数名をJSX内でアロー関数を用いて呼び出します。
useState関数を呼び出すconst App = () => { stateを変更させる関数名(変更したstateの値) };useStateの実用例
useStateを使ったカウントアップ関数の例を紹介します。
useStateの使用例import React, { useState } from 'react'; const App = () => { const [count, setCount] = useState(0); return ( <div className="App"> <div> <p>{count}</p> <button onClick={() => setCount(count + 1)}> Click </button> </div> </div> ); }; export default App;最後に...
今回は、useStateの使い方を紹介しました。
最後まで、読んでいただきありがとうございました。
- 投稿日:2021-03-01T09:25:01+09:00
React + TypeScript での forwardRef 実装サンプル
- TS の情報に乏しく無駄にハマったのでメモ程度に
確認環境
- React 17.0.1
- TypeScript 4.1.3
実装方法
- 今回はサンプルとして
<input />
をラップしたコンポーネントのフォーカスを変更するためにref
を使います
Child.tsx
Child.tsximport { forwardRef } from 'react'; export type ChildProps = { type: 'text' | 'password' | 'number'; onChange(changeValue: string): void; }; // function 記法でないと ESLint が怒るので無効化 // eslint-disable-next-line react/display-name export const Child = forwardRef<HTMLInputElement, ChildProps>( // このpropsに明示的な型定義がないと型エラーが出ます (props: ChildProps, ref) => { const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => { props.onChange(ev.target.value); }; return <input ref={ref} type={props.type} onChange={(ev) => onChange(ev)} />; } );
Parent.tsx
- 下側の
<Child />
だけフォーカスが行くようにしてますParent.tsximport { useEffect, useRef } from 'react'; import { Child } from './Child'; export const Parent = () => { const ref = useRef<HTMLInputElement>(null); useEffect(() => { ref?.current?.focus(); }); return ( <ul> <li> <Child type={'text'} onChange={(ev) => console.log('top input', ev)} /> </li> <li> <Child ref={ref} type={'text'} onChange={(ev) => console.log('bottom input', ev)} /> </li> </ul> ); };
- 投稿日:2021-03-01T09:25:01+09:00
TypeScript での forwardRef 実装サンプル
- TS の情報に乏しく無駄にハマったのでメモ程度に
確認環境
- React 17.0.1
- TypeScript 4.1.3
実装方法
- 今回はサンプルとして
<input />
をラップしたコンポーネントのフォーカスを変更するためにref
を使います
Child.tsx
Child.tsximport { forwardRef } from 'react'; export type ChildProps = { type: 'text' | 'password' | 'number'; onChange(changeValue: string): void; }; // function 記法でないと ESLint が怒るので無効化 // eslint-disable-next-line react/display-name export const Child = forwardRef<HTMLInputElement, ChildProps>( // このpropsに明示的な型定義がないと型エラーが出ます (props: ChildProps, ref) => { const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => { props.onChange(ev.target.value); }; return <input ref={ref} type={props.type} onChange={(ev) => onChange(ev)} />; } );
Parent.tsx
- 下側の
<Child />
だけフォーカスが行くようにしてますParent.tsximport { useEffect, useRef } from 'react'; import { Child } from './Child'; export const Parent = () => { const ref = useRef<HTMLInputElement>(null); useEffect(() => { ref?.current?.focus(); }, []); return ( <ul> <li> <Child type={'text'} onChange={(ev) => console.log('top input', ev)} /> </li> <li> <Child ref={ref} type={'text'} onChange={(ev) => console.log('bottom input', ev)} /> </li> </ul> ); };
- 投稿日:2021-03-01T08:14:10+09:00
AWS Amplifyでリソース(API, Auth)構築からフロントエンド(React)へ導入するまでの手順をまとめました
はじめに
AWS Amplifyを使うとサーバレスのバックエンドを簡単につくれるという話をききました。個人でアプリ開発をやってみたいなーという気持ちがあったのですが、バックエンド構築の手間がネックでなかなか手をつけられずにいたので、この機会にAmplifyを学習してみることにしました。
以下はAPIとAuthリソースを構築してフロント側に実装するまでのまとめです。AWS Amplify とは
CLIでコマンドをポチポチするだけでクラウドにバックエンドリソース(S3やAPI GatewayなどのAWSサービス)を設定することができ、サーバレスバックエンドを簡単に構築できるサービスです。このサービスを使うことで、アプリ開発を超高速に行うことができます。
コマンドで作成できるリソースとしては以下のようなものがあります。
- Auth: Amazon Cognito(SignIn/SignUp機能を追加)
- Analytics: Amazon Pinpoint(ユーザのセッションやイベントを記録)
- Storage: Amazon S3
- Caching: Amazon Cloudfront
- API: API Gateway+Lambda(REST)やAppSync(GraphQL)
Black Beltの資料にもっと詳しい内容が載っています。
Amplify CLI の導入
バックエンドリソースをポチポチするだけで作成するには、Amplify CLIの導入と自分のAWSアカウントとの紐付けが必要になります。
導入方法は公式Docsに書いてあるので割愛しますが、簡単にまとめると以下のことを行っています。
- Amplify CLIのインストール(Node.jsとnpmの事前導入が必要)
- Amplifyの設定でAWSリソースを作成するためのIAMユーザを新規作成
- アクセスキーIDとシークレットアクセスキーを入力してAmplify CLIとIAMユーザを紐付け
アプリ構築
AmplifyでGraphQLやAuthなどのバックエンドリソースを構築し、Reactで作成したアプリでこれらを利用するところまでをまとめました。
最初にnpx create-react-app <app名>
でプロジェクトを作成してください。バックエンド構築
まずはプロジェクトにamplifyを導入します。以下のコマンドをうつと、デフォルトのエディタや使用フレームワークに関する質問がでてくるのでそれに答えます。
amplify init ? Enter a name for the project chatapp ? Enter a name for the environment dev ? Choose your default editor: Visual Studio Code ? Choose the type of app that you're building javascript Please tell us about your project ? What javascript framework are you using react ? Source Directory Path: src ? Distribution Directory Path: build ? Build Command: npm run-script build ? Start Command: npm run-script start Using default provider awscloudformation ? Select the authentication method you want to use: (Use arrow keys) ? Select the authentication method you want to use: AWS profile For more information on AWS Profiles, see: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html ? Please choose the profile you want to use defaultAPI(GraphQL)リソースの構築
以下のコマンドで質問に答えていくと、
amplify/backend
の直下にapi
フォルダが作成されます。amplify add api ? Please select from one of the below mentioned services: GraphQL ? Provide API name: chatapp ? Choose the default authorization type for the API API key ? Enter a description for the API key: ? After how many days from now the API key should expire (1-365): 365 ? Do you want to configure advanced settings for the GraphQL API No, I am done. ? Do you have an annotated GraphQL schema? No ? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)schema.graphqlでスキーマを定義します。
type Post @model { id: ID! postOwnerId: String! postOwnerUsername: String! postTitle: String! postBody: String! createdAt: String comments: [Comment] @connection(name: "PostComments") #relationship likes: [Like] @connection(name: "PostLikes") } type Comment @model { id: ID! commentOwnerId: String! commentOwnerUsername: String! post: Post @connection(name: "PostComments") content: String! createdAt: String! } type Like @model { id: ID! numberLikes: Int! likeOwnerId: String! likeOwnerUsername: String! post: Post @connection(name: "PostLikes") }typeに@modelというディレクティブをつけると、データソース(DynamoDB)との連携やresolverを自動で生成してくれます。
また、amplify codegen
でsrc/graphqlにクライアントソースコード側でもアクセスできるライブラリも自動で生成してくれます。ディレクティブについては、こちらのサイトが参考になりました。
amplify push
を実行して以下の質問に答えると、AWSのリソース(AppSync)が構築されます。amplify push | Category | Resource name | Operation | Provider plugin | | -------- | ------------- | --------- | ----------------- | | Api | chatapp | Create | awscloudformation | ? Are you sure you want to continue? Yes ? Do you want to generate code for your newly created GraphQL API Yes ? Choose the code generation language target javascript ? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js ? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes ? Enter maximum statement depth [increase from default if your schema is deeply nested] 2
amplify console api
でAppSyncの画面を開くと、作成したSchemaを確認することができます。
Authリソースの構築
amplify add auth
を実行した後にamplify push
でAWSのリソース(Cognito)が構築されます。amplify add auth Using service: Cognito, provided by: awscloudformation The current configured provider is Amazon Cognito. Do you want to use the default authentication and security configuration? Default configuration Warning: you will not be able to edit these selections. How do you want users to be able to sign in? Username Do you want to configure advanced settings? No, I am done.フロントエンドの設定
構築したAWSリソースをフロントエンド(React)で使う方法をまとめました。
API(GraphQL)
作成したQueryとMutationの読み込み方をまとめました。
Query
npm install aws-amplify aws-amplify-react
で必要なライブラリを導入し、作成したクエリを読み込んでAPI.graphql(graphqlOperation(listPosts))
のようにするとクエリが実行されます。このとき、データを取得した後に表示を行いたいので、非同期処理(async~await)を行っています。import { listPosts } from '../graphql/queries'; import { API, graphqlOperation } from 'aws-amplify'; const getPosts = async () => { const result = await API.graphql(graphqlOperation(listPosts)); };Mutation
こちらもクエリと同様でgraphqlフォルダから読み込んで実行します。
以下はdeletePostの例です。削除するpostの指定のために、postIdを引数としてとっています。const handleDeletePost = async (postId) => { const input = { id: postId, }; await API.graphql(graphqlOperation(deletePost, { input }));Auth
withAuthentificator
をインポートしてAppをラッピングしてあげます。import './App.css'; import { DisplayPosts } from './components/DisplayPosts'; import { CreatePost } from './components/CreatePost'; import { withAuthenticator } from 'aws-amplify-react'; function App() { return ( <div className="App"> <CreatePost /> <DisplayPosts /> </div> ); } export default withAuthenticator(App, { includeGreetings: true });作成したアカウントはCognitoのユーザプールで管理されます。
おわりに
React Native+Amplifyでお腹弱い人向けのサービスでもつくろうかなと思っています。
- 投稿日:2021-03-01T02:35:28+09:00
Reactプロジェクトで this.hoge.bind(this) とかやってる人に言いたい
これを見てくれ
class CoolButton { constructor() { this.onClick.bind(this); } onClick() { ... } render() { return <button onClick={this.onClick}>Cool</button>; } }このbindを見て疑念を抱いた君、正解だ
イベントハンドリング部分でアロー関数でイベントを書くようにすればこんなthisは要らないclass CoolButton { onClick() {} render() { return <button onClick={() => this.onClick()}>Cool</button>; } }結論
onHogehoge のようなイベントはアロー関数で指定してあげよう
- 投稿日:2021-03-01T02:15:23+09:00
React Hookが何かをかいつまんで昨日の自分に教える
昨日の自分よ、見てるか~‘?
参考: https://ja.reactjs.org/docs/hooks-intro.html
関数コンポーネントにステートを導入できる機能みたいだ。導入された理由の一つにビジネスロジックの分離?があるみたいだが理屈がよくわからないのでいったん忘れてよい。
sample code
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
const [count, setCount] = useState(0);
countはステート変数
setCountはステートを変更する関数のようだ
useEffect
はステート変更時のイベントをかけるみたい。おわり
setState とかの新しい書き方ってこと?
- 投稿日:2021-03-01T01:13:00+09:00