OmniAICreator/Qiita-1.07M huggingface dataset:
【GitHub】Issuesの基本的な使い方

#はじめに
この記事では、GitHubのIssuesの基本的な使い方についてまとめました。
⚠️当方初学のため認識違いがある可能性大です
誤りを見つけた際はコメントにて指摘していただけると幸いです🙇‍♀️🙇‍♂️


#参考
この記事は以下の記事を参考に作成しました。

- [チーム開発を変える「GitHub」とは？〜Issuesの使い方〜【連載第3回】](https://seleck.cc/647)



#Issuesとは
プロジェクトやソースコードの課題を管理するための機能。
Issues機能は、リポジトリ単位に管理されている。

#基本的な使い方


GitHubのトップページから[Issues]タブを選択し、[New issue]をクリック。
![スクリーンショット 2021-01-24 17.11.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790168/1551ae48-aa6e-d044-0b8c-fa3996aa9828.png)


以下の画面になったら、タイトルとコメントを入力。
タイトルは課題の内容（機能、問題など）を端的に表し、コメントでは仕様や手順など詳細に書いていく。
![スクリーンショット 2021-01-24 17.14.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790168/43fdd1ea-9b68-4de8-179f-3cc9d1e832fe.png)


[Submit new Issue]をクリックするとIssueの登録が完了し、以下の画面になる。
このリポジトリにアクセス権限のある人なら、誰でもIssueに対してコメントができる。
Issueが解決したら[Close issue]ボタンをクリックしてクローズする。
![スクリーンショット 2021-01-24 17.19.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790168/8acb3c32-2fa2-0e33-c755-e4434295cbec.png)


クローズしたIssueは完全に消える訳ではなく、Issueの一覧から確認できる。

![スクリーンショット 2021-01-24 17.22.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790168/bde653aa-8ded-a536-3312-24f3f024ce10.png)



#その他各種機能

### - Assignee
Issueに担当者を割り当てる機能。
Issue画面のサイドバーにある[Assignee]という文字をクリックすると、ユーザーの選択画面が出てくる。
誰がどのくらいのタスクを抱えているかが一目で分かるようになる。

### - Milestone
Issueに締め切りをつける機能。
GitHubでは、Issueごとに期日を切るのではなく、マイルストンを先に置いてそれにIssueを紐付ける。

### - Label
Issueにラベルを付けて分類できる。
【Vue.js】classをデータにバインディングする方法を図解で理解する。

Vue.jsでは、v-bindでclass属性を設定した際に、下記の様なオブジェクトを渡すことにより、class属性の値を適用、不適用を切り替えることができる。

![65b36a9f1709b0faed926d7badba95e5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/28751133-d939-4d63-be81-33ff29548225.png)

```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>

<style>
  .red {
    background-color: red;
  }
  .blue {
    background-color: blue;
  }
</style>

<div id="app">
  <h1 :class="{red:true, blue:false}">Hello</h1>
</div>

<script>
  new Vue({
    el: '#app',
  })
</script>

```
![2b23b34f73c55d908de52b09886428b4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/e06abb00-7586-2464-a2bc-668ff5bdabd2.png)

```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>

<style>
  .red {
    background-color: red;
  }

  .blue {
    background-color: blue;
  }
</style>

<div id="app">
  <h1 :class="{red:false, blue:true}">Hello</h1>
</div>

<script>
  new Vue({
    el: '#app',
  })
</script>
```

##v-bindされたclass属性の値にオブジェクトを渡して動的に切り替える。

```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>

<style>
  .red {
    background-color: red;
  }

  .blue {
    background-color: blue;
  }
</style>

<div id="app">
  <h1 :class="classChange">Hello</h1>
  <button @click="change">切り替え</button>
</div>

<script>
  new Vue({
    el: '#app',
    data: {
      isActive: true
    },
    methods: {
      change: function () {
        this.isActive = !this.isActive
      },
    },
    computed: {
      classChange: function () {
        return {
          red: this.isActive,
          blue: !this.isActive,
        }
      }
    }
  })
</script>
```
データの流れ

![IMG_4CD730BA51B2-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/eb17fdf9-90be-0269-51f5-d3af2c27926d.jpeg)
AppStoreConnectで連絡先情報が保存されない

# はじめに

AppStoreにアプリを出すとき、連絡先情報が保存されない状態が2週間ぐらい続き、また対処法がなかったため(Appleに問い合わせても解決しなかった)ため、ここに対処法を示します。

# エラー内容
AppReviewに関する情報のサイン情報、連絡先情報を入れ、右上の保存を押したところ、保存中のまま更新されない状態になった

![S__83935236.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/970027/7b1d40c3-07a2-1ea4-9d0b-2f5d9b6bd485.jpeg)

# エラー修正方法
電話番号を080~と書いていたところ、+81 080~と書くことで保存ができるようになった。
その他の部分はまだ変更をしなくても問題ありません。
え、まだpreventDefaultとstopPropagationをいちいち入力してるの？？

今回はテクニック集として、独自のショートカットキーを設定していきます。

Javascriptのwindowオブジェクトを使う際にちゃんと``perventDefault``や``stopPropagation``を使っていますか？？

これをやらないと、思わぬところで自分の意図しない関数が実行されたりということが発生します。

ただ、これを毎回入力するの結構めんどいですよね。

ここで、vscodeでショートカットキーを設定しちゃいましょう！！

こちらの記事[=（イコール）打った後の""（ダブルクォーテーション）って遠くない？？？解決策は・・・](https://qiita.com/akki-memo/items/05f0943eade883243fa1)を見て頂くと、ショートカットキーの設定のやり方が載っているので是非ご覧ください！

こちらの記事と同じように、まずはショートカットキーを設定します。

僕は``ctrl+shift+e``と設定しました。

次に、以下のように設定します。

```
{
"key": "ctrl+shift+e",
"command": "type",
"args": { "text": "event.preventDefault()\nevent.stopPropagation()"},
"when": "editorTextFocus"
}
```

``\n``で改行を行っています。

vscode再起動。

``ctrl+shift+e``と打つと、``event.preventDefault()``と``event.stopPropagation()``が表示される思います！

このようにしてショートカットキーをじゃんじゃん自分好みに設定していってください！！！

以上、「え、まだpreventDefaultとstopPropagationをいちいち入力してるの？？」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
【メモ】WSL2で"Error: 0x80370102"が出たとき

# 事象
デスクトップPCを久々に起動しました。
SSDとかGPUを一新したので、新規でWindowsを再インストール、WSL2でUbuntu 20.04LTSを導入したら以下のエラーが表示・・・。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163185/ee57f524-c905-e08c-b4e8-a560b8de907f.png)

# 一言でいうと
仮想化忘れてるよ。

# 解決法
あちこちのWebサイトにも書かれていますが、BIOS( or UEFI)を開いてCPUの仮想化技術を有効化したらOKです。

# 参考
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10
【AWS】EC2を間違えて終了（削除）してしまわないよう、終了保護の設定をする

#はじめに

本記事では、AWSのマネジメントコンソールからEC2インスタンスの管理をする時に、
誤操作でうっかりインスタンス（サーバー）を<font color="Red">**「終了」（削除）**</font>してしまわないように対策する方法をご紹介します。
(インスタンスを一度削除してしまうと、**もう復元することはできない**ので要注意です。。！）

![スクリーンショット 2021-01-24 16.20.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/cf3fb222-db19-39ca-7753-0b73c7c1a3a7.png)

画像の例では、EC2のマネジメントコンソールで「Test」という名前のインスタンスを選択した状態で、**「インスタンスの状態」**タブを開いています。
すると、

<font color="Blue">**①インスタンスを停止**</font>
<font color="DarkOrange">**②インスタンスを終了**</font>

等を選択できるようになります。
インスタンスを停止したい時は<font color="Blue">**①**</font>を選択しますが、
例えばここで間違えて<font color="DarkOrange">**②**</font>を選択してしまうと、**インスタンスが削除**されてしまいます。
大事なデータやアプリが全部消えてしまっては、一大事。。

誤操作でインスタンスを削除してしまわないように対策する設定をしていきましょう！

#終了保護の設定をする

以下の順にクリックしていきます。
EC2のマネジメントコンソールの**「アクション」**タブ ＞ **「インスタンスの設定」** ＞ **「終了保護を設定」**


![スクリーンショット 2021-01-24 16.52.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/acf001d2-95d2-4c64-4b1d-37f0acf7b2fb.png)

あとは、終了保護の設定画面で、**「有効化」**にチェックを入れて、**「保存」**ボタンをクリックすれば設定は完了です！

![スクリーンショット 2021-01-24 17.01.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/a9c30f48-bba2-fa68-883c-ba6e3caeb0fa.png)

###終了保護が設定できたか確認

それでは、ちゃんと終了保護設定が反映されているかを確認してみます。
先ほどと同様に、**「インスタンスの状態」**タブを開いて、**「インスタンスの終了」**をクリックしてみます。（クリックできちゃう）

すると赤い背景色で、<font color="Red">**「インスタンスxxxxxの終了に失敗しました」**</font>というエラーメッセージが表示され、ちゃんとインスタンスの終了から保護されていることがわかります。

![スクリーンショット 2021-01-24 17.06.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/22d98e40-65ee-04e7-eeee-64f0b4c5e7f7.png)

もし逆に、インスタンスを終了したい時は、終了保護設定を無効にすればOKです。

###インスタンスの新規作成時にも、終了保護設定ができる

なお、**「インスタンスを起動」**ボタンをクリックして、
インスタンスを新規作成する時の
**「ステップ３：インスタンスの詳細の設定」**のページでも終了保護設定の有効化を設定することができます。
![スクリーンショット 2021-01-24 17.17.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/c974687a-8d9e-8329-16f3-a94b06826639.png)

#最後に
今回は、EC2インスタンスを終了（削除）から保護をする設定方法をご紹介しました。
もし更に対策を万全にするのであれば、この他にもインスタンスのバックアップやスナップショップを取ったり、AMIを残しておくと安全です！

それでは、この記事が少しでもお役に立てば幸いです。
Mac(M1)でpython環境構築(はじめて環境構築をする人向け)


# Mac(M1)へ買い換えたので環境構築を行います

 5年ぶりくらいにMacを買い換えたのでpython環境構築をする必要があり、せっかくなのでまとめました。
Macで、はじめてpythonの環境構築を行う人に役立てばと思います。

そしてQiitaでの投稿ははじめてなので、見辛いかもしれません。。。
今後memoの感覚で投稿できたらと思います。
##### 以下を使用していきます
Mac(BigbSur Apple M1チップ)
Xcode
Homebrew
pip3
venv(仮想環境構築)

## まず全体の流れ
1. 仮想環境構築とは
2. Xcodeをインストール
3. Homebrewをインストール
4. 仮想環境作成　virtualenvをインストール
5. pythonをインストール

## 1.仮想環境構築とは
　pythonを使用していくにあたり、さまざまなパッケージ（モジュールをまとめたもの）をインストールします。
python初心者のころは（まだ初心者ですが）いろんなチュートリアルを見ては、いろんなパッケージファイルをインストールしてしまい、気づけばとんでもない数のパッケージファイルをインストールしてたってことにもなりかねません。

*そこで！*仮想環境というものを作成し、その中でpythonを管理していきます。
そうすることで、作りたいものごとにパッケージを管理することができるよになります。

使わなくなった、失敗した環境に関してはなにも考えずに消してしまえばOKなので安心です。
仮想環境の作り方は*4.仮想環境作成*にて説明します。
では、必要なものをインストールしていきましょう！

## 2.Xcodeインストール
まずはAppStoreでXcodeをインストール
（サイズが11.6GBもあるため少し時間かかります。嘘でしょ。）
一度起動して「Xcode and iOS SDK License Agreement」が表示されるので
[Agree]をクリックします。


※Xcodeを全てインストールする必要はなくApple製品のアプリ開発をしなければ以下コマンドで「Command Line Developper Tools」をインストールするだけでOK

```terminal:terminal
$ xcode-select --install
```
これでXcodeのインストールは完了

## 3.Homebrewのインストール
![スクリーンショット 2021-01-24 13.15.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664637/76c61fa4-4c7e-903d-0863-ed7d6ed43f37.png)
HomebrewはAppleStoreなどでインストールできない必要なものをインストールするためのツールです。（アイコンがビールで可愛いです。）

[Homebrew](https://brew.sh/index_ja)へアクセスし記載されてあるコマンドをターミナルへコピペ！
と、言いたいところなのですが、[Homebrew_alternative](https://docs.brew.sh/Installation#alternative-installs)に書いているようにM1チップ版のインストールは`opt/homebrew`に展開する手順になるそう。
将来的にIntel/M1両対応が完了すれば従来通り/usr/localで利用できるようになるよう。待ってもいられないので[こちら](https://qiita.com/asip2k25/items/c019c766a53f4b28df6d#homebrew%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB-on-m1-mac)でM1Mac用環境構築を綺麗にまとめられてたので参考にし、インストール行いました。

```
% cd /opt #ディレクトリ移動
% sudo mkdir homebrew　#rootユーザでディレクトリ作成
% sudo chown -R $USER .　#ログインユーザに所有権設定
% curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew　#Homebrewインストール
% vi ~/.zshrc
export PATH=/opt/homebrew/bin:$PATH　#Homebrewへのパスを追加
% source ~/.zshrc #シェルに反映
% brew -v　#反映されているか確認
% brew update　#更新
```
インストールできているかチェックするために`brew doctor`を実行
`Your system is ready to brew.`になれば、おめでとうございます。
インストール完了です。
## 4.仮想環境作成
*1.仮想環境構築とは*で説明したように直接Mac下にpythonをインストールすると後々、めんどくさいことになるので、仮想環境という箱を作成し、その中に使用するだけのモジュールをインストールしてあげます。
仮想環境を作成する方法は色々あるのですが、今回はvenvを使用します。
(venvはPython3.4以降であれば標準で使用できます)

venvで仮想環境を作成

```terminal:terminal
python3 -m venv myenv
```
venvで仮想環境を実行

```terminal:terminal
source myenv/bin/activate
```

これで作成した仮想環境内に入ることができました
ターミナルのUser名の前に(myenv)と仮想環境名が入っていることを確認してください。
仮想環境内で作業している時はpythonコマンドは自動的に正しいバージョンのpythonを参照しに行くので`python3`コマンドの代わりに`python`が使用できます。

以上で仮想環境構築は終了です。

`pip install hogehoge`でいろんなモジュールをインストールして試してみたください。

また作成した仮想環境を削除したい時は作成したフォルダを削除するだけです。
簡単ですね！

仮想環境を初期化したい場合は`deactivate`で仮想環境から抜けて以下コマンドを実行すれば初期化されます。

```terminal:terminal
python3 -m venv --clear myenv
```

他にも色々なコマンドがあるので、便利そうなものがあれば、またまとめたいと思います！
UniRxのUIにまつわる処理3選

様々な使い方のあるUnityのライブラリ「UniRx」の中でも、
UIにまつわる処理を紹介します。

[その1. ReactiveProperty](#その1-reactiveproperty)
[その2. BindToButtonOnClick](#その2-bindtobuttononclick)
[その3. BindToOnClick](#その3-bindtoonclick)

#その1. ReactiveProperty
```cs:Sample1
using UnityEngine;
using UniRx;

public class Sample1 : MonoBehaviour
{
    //int level; とほぼ同じ使い方ができる。
    ReactiveProperty<int> level = new ReactiveProperty<int>();

    void Start()
    {
        level.Subscribe(Talk);
        //level.Subscribe(arg => Talk(arg)); のようなラムダ式でも可
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            level.Value++;  //.Valueで中身にアクセスする
        }
    }

    void Talk(int level)
    {
        Debug.Log("level up!" + level);
    }
}
```
<font color="Gray">Spaceを押すとlevelが上がり、levelが上がると同時にlevel up!と表示される。</font>
>ReactivePropertyは、ざっくり言うと、値の変更を通知してくれる変数のようなものです。
>new ReactiveProperty<T>()で作成し、Valueから値を取得・設定します。
([UniRxのReactivePropertyについて](http://nobollel-tech.hatenablog.com/entry/unirx-reactive-property) より引用。詳しい使い方も書かれています。)

Subscribe関数から、値の変更時に呼ばれて欲しい関数を登録することができます。
値と常に同期して欲しいことの多いUIの変更に便利です。

#その2. BindToButtonOnClick
```cs:Sample2
using UnityEngine;
using UnityEngine.UI;
using UniRx;

public class UniRxSample2 : MonoBehaviour
{
    [SerializeField] Button button;

    //bool can_press; とほぼ同じ使い方ができる。
    ReactiveProperty<bool> can_press = new ReactiveProperty<bool>();

    // Start is called before the first frame update
    void Start()
    {
        can_press.BindToButtonOnClick(button, _ => Click());
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            can_press.Value = true;
        }

        if (Input.GetKeyDown(KeyCode.F))
        {
            can_press.Value = false;
        }
    }

    void Click() { Debug.Log("Click"); }
}
```
<font color="Gray">can_pressというReactiveProperty<bool>の値が、Tキーを押すとtrueに、Fキーを押すとfalseに変更される。can_pressの値が変更されるとbuttonのinteractableも変更される。</font>

BindToButtonOnClickは、ボタンに"押下された際の処理"と"押せるかどうか"、つまりonClickとinteractableを同時に登録するような関数です。
bool型のReactivePropertyから呼び出すことができます。

ちなみに、can_press.SubscribeToInteractableでinteractableのみ登録ができます。

ButtonのOnClickAsObservable()関数は、onClickをIObservableに変換する関数です。
Where関数で、bool型の関数を入力することができます。そのbool型の関数の結果がtrueの場合のみしか登録した関数を呼びださない、という処理が可能になります。

#その3. BindToOnClick
```cs:Sample3
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UniRx;

public class UniRxSample3 : MonoBehaviour
{
    [SerializeField] private Button button;

    void Start()
    {
        button.BindToOnClick(_ => Observable.FromCoroutine(LevelingUp));
    }

    IEnumerator LevelingUp()
    {
        int level = 0;
        for (int i = 0; i < 100; i++)
        {
            level++;
            yield return null;
        }
        Debug.Log("level up!");
    }
}
```
<font color="Gray">buttonを押すと、コルーチンが呼ばれ、完了するまでButtonのinteractableがfalseとなる。</font>

BindToOnClickはButtonにIObservableを返す関数を登録することができる関数です。
入力したIObservableが完了するまで、interactableがfalseとなります。
アニメーションを伴う処理や、サーバーと通信する処理などをする間、Buttonを押せなくするのに便利です。
CoroutineはFromCoroutine関数でIObservableに変換することができます。
Firebase hostingのプレビュー機能がすごい

#プレビュー機能って？
firebaseが現在ベータ版として出している機能で、実際にデプロイする前にwebアプリケーションをプレビューできる機能です。
主な用途としては、PR時にプレビューサイトに自動でデプロイして、デザインや機能の確認をするという感じです。

#実際の使い方
実際の使い方は以下のドキュメントを見れば書いてあります。
https://firebase.google.com/docs/hosting/github-integration

ドキュメント通りにコマンドを実行していくと、gitのレポジトリの認証をして勝手にgithub actionのymlファイルを生成してくれます。しかもfirebaseのapi keyは自動的にgitのシークレットに保存されます！！
あとは、PRを出すだけという超簡単設計！！是非お試しあれ〜
[参戦記] ABC190

**パフォーマンス**
マイワースト２

**A**
問題なし

**B**
Pythonの動的型付け仕様への認識が甘く、整数浮動小数点演算が発生していることに気付かず、そこでの誤差が不正確な判定を起こし、WAを招いた。自己解決したものの、基本的ミスに動揺する。

**C**
２０分以上掛ったが、時間計算量の問題であること、全探索で間に合いそうであることは結論できた。しかし、Python3で単純な全探索の時間計算量を確認した所、それだけでTLEすることが判明する。自分の考察にそれなりに自信があり、実際に模範的考察でもあったのだが、それと矛盾する実行結果により混乱する。再検討しても問題点が不明なので、Dに移る。
実は、PyPy3で実行すれば問題なかった。

**D**
B,Cで大いに混乱し、もともと精神的に不調だったこともあり、これも模範的考察に近い形まで考え進めたものの、落ち着いて十分に検討することができない。DFSではないかと思うが、DFSにするまでもないかも、DFS設計内容を明確化できない、という辺りで思考が右往左往する内にタイムオーバーになる。

**反省**
結果的に２完の惨憺たる結果に終わったが、実は取り組み内容はそれほど悪いものではなく、悪い精神状態からすると良く頑張ったとは思う。
精神的不調はさておき、確実に改善できる問題点として、今週もある程度勉強できたのだが、それが逆にアルゴリズムとの紐付けを意識し過ぎてしまい足を引っ張った。しかし、前回の反省からアルゴリズムと一定距離を置けて取り組めてもいたので、もっと意識的に自分を信じて落ち着いて取り組む必要がある。具体的な問題点として、プログラム言語仕様の理解不足があった。データ型や言語の特徴をより正確に認識しておく必要がある。

**蛇足**
参戦記は、基本的に自分の反省記録として始めたものだ。しかし、鋭いコメントを頂戴し驚いている。自分の子どものような年齢の人が、自分より遙かに上手であったり、見ず知らずの人に親切にアドバイスをする人がいたりするのは、自分は様々な業界を経験してきたが、珍しい文化であると思うし、異業種からチャレンジするには良い文化だと思う。自分はもう若くないが、精進を続けて、この業界でも通用できるようになりたいと思う。
flutterでcameraプラグインを使用する際、ビルドすると”パッケージandroid.support.annotationは存在しません”と表示されてしまう

# 症状
pubscpec.yamlにcameraプラグインを追加してビルドした際に以下のエラーが表示される。  

```  
パッケージandroid.support.annotationは存在しません
```

# 対策
cameraプラグインのバージョンをあげる

```
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter


#  camera: ^0.2.4    # 0.2.*系は古いので新しくする
　camera: ^0.5.8+5


flutter:

  uses-material-design: true
```
[自分用メモ]TypeScriptの書き方まとめ~型と関数と配列~

#配列
- タプル型

このように配列の型を厳格に決めることができます。

```typescript

const book: [string, number, boolean] = ['business', 1500, false];
```

#列挙型
- enum

列挙型は```enum CoffeeSize```とすることで定義できます。
列挙型では```size: CoffeeSize.TALL```のようにenumで列挙したまとまりを使うことができます。
下記のようにenumを使うことで、sizeに入る値をSHORT,TALL,GRANDE,VENTIのみに定義することができます。

```typescript
enum CoffeeSize = {
  SHORT= 'SHORT',
  TALL= 'TALL',
  GRANDE= 'GRANDE',
  VENTI= 'VENTI'
}

const coffee = {
  hot: true,
  size: CoffeeSize.TALL
}
```

列挙型では下記のように列挙型の値を取り出すこともできます。

```typescript
coffee.size = CoffeeSize.SHORT;
```

#Union型

数字か文字列にしか入らないようにできます。

```typescript
let unionType: number | string = 10;
let unionTypes: (number | string)[]  = [21, 'hello']//配列
```

#リテラル型

- リテラル型は下記のように特定の値(apple)しか入れることができない

```typescript
const apple: 'apple' = 'apple'
```

- 下記のようにリテラル型とユニオン型を組み合わせることでenumのように使うことができる。
値が2,3個の時に使うとenumのように冗長にならなくて済む

```typescript
let clothSize: 'small' | 'medium'  | 'large' = 'large';
const cloth: {
  color: string;
  size: 'small' | 'medium'  | 'large' 
} = {
  color: 'white',
  size: 'medium'
}
```

#typeエイリアス
typeエイリアスを使うことで上記のリテラルとユニオンを組み合わせたコードを短くすることができます。

```typescript
type ClothSize = 'small' | 'medium'  | 'large'//ClothSizeにtypeで型を指定
let clothSize: ClothSize = 'large';//ClothSizeをそのまま使うことができます
const cloth: {
  color: string;
  size: ClothSize//typeエイリアスを使用することで 'small' | 'medium'  | 'large'が不要になります
} = {
  color: 'white',
  size: 'medium'
}
```

#関数

- 関数宣言に型をつける場合

引数と戻り値に型をつけることができ、引数が無い場合はvoidが返されます

```typescript
function add(num1: number, num2: number): number {
  return num1 + num2
}

function SayHello(): void {//引数無い場合はvoidが返される
  console.log('Hello');
}
console.log(SayHello());//undefinedが返される
```

- 関数を保持する変数に型をつける場合

変数に型をつける時は=>を用いて型をつけることができます。関数宣言の時の型注釈は「:」なので注意しましょう。



```typescript
const anotherAdd: (n1: number, n2: number) => number = add;

const anotherAdd: (n1: number, n2: number) => number = function　(num1: number, num2: number): number {
  return num1 + num2　//このように関数を直接入れることも可能で、無名関数としても挿入できます
};

const anotherAdd = function　(num1: number, num2: number): number {
  return num1 + num2　//型はどちらかがあればOKです
};
```

- アロー関数
この様にすっきり書くことができます。

```typescript
//パターン１(右に書く場合)
const doubleNumber = (num: number): number => num * 2;//返す値が一つであれば{}もreturnもいらない

//パターン２(左に書く場合)
const doubleNumber: (num: number) => number = num => num * 2;
//左に書く場合はt
```
#コールバック関数

下記では第２引数に```cb: (num: number => number)```というnumberという型を持つ、戻り値がnumberであるコールバック関数があります。

```typescript
function doubleAndHandle(num: number, cb: (num: number) => number): void {//関数宣言だから「:」
  const doubleNum = cb(num * 2);//コールバック関数
  console.log(doubleNum);
}
doubleAndHandle(21, doubleNum => {
  return doubleNum
});
```
[React] Reactの学習をします（2-4）OR マッパーによるデータベースの利用

#Reactの学習をします（2-4）

引き続き、Reactの学習をしています。

前回の記事　：　[[React] Reactの学習をします（2-3）React Router を用いた複数ページ Web アプリの開発](https://qiita.com/IwashiMorino/items/aa824df02056cf0bc16f "[React] Reactの学習をします（2-3）React Router を用いた複数ページ Web アプリの開発")

##教材

[Reactチュートリアル2：レビューサイトを作ろう](https://zenn.dev/likr/articles/react-with-heroku#or-%E3%83%9E%E3%83%83%E3%83%91%E3%83%BC%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E5%88%A9%E7%94%A8 "Reactチュートリアル2：レビューサイトを作ろう")

引き続き、likr さんが公開している「Reactチュートリアル2：レビューサイトを作ろう」という記事を教材に学習させて頂きます。

素晴らしい教材をありがとうございます。

##成果物

このチュートリアル2につきましては、チュートリアルの通りに作成し既にNetlifyに公開させて頂いております。

こちらです　→　[日大文理ラーメンレビュー](https://friendly-hopper-e0a9d5.netlify.app/ "日大文理ラーメンレビュー")

##学習日記

既に作成済ですが、少しずつチュートリアルの内容を読み返してみたいと思います。

※ 教材から箇条書き的に抜粋させて頂きます。

##OR マッパーによるデータベースの利用

>・次はデータベースを導入して、実際のデータをやり取りできるようにしていきましょう。

>・ここからは、ローカルの開発環境からアクセスできる **PostgreSQL** のサーバーを用意しておく必要があります。

PostgreSQLを自分のPCにインストールしておきます。

PostgreSQL公式ページ　：　[PostgreSQLのダウンロード](https://www.postgresql.org/download/ "PostgreSQL")

そして、review_app というデータベースを作成しました。

※ 私のPCはWindows10ですので、PowerShell にて下記コマンドを実行します。

CREATE DATABASE review_app;


>・SQL で取り出した情報は JavaScript 等のプログラミング言語で扱いやすい状態になっていると便利でしょう。

>・O/R マッパーは、SQL の組み立てやクエリ結果のオブジェクトへの変換を行うライブラリで、Node.js では **Sequelize** という有名な O/R マッパーがあります。

チュートリアルに書かれている通りに作業していきます。

##Heroku による API サーバーの公開

>・API サーバーは **Heroku** を、フロントエンドは **Netlify** を使って公開します。

※ heroku pg:push するとき、エラーが発生してうまくデータを送ることができませんでした。

※ PostgreSQL のバージョンの問題であるように思われたため、いくつかのバージョンで試行錯誤しました。

※ 最終的にバージョン11を利用することにしました。

　現在、Heroku では、特に指定しないとバージョン12が導入されます。
　　→　[Heroku PostgreSQL version-support](https://devcenter.heroku.com/articles/heroku-postgresql#version-support "heroku postgresql version-support")

　ローカル側、Heroku側、ともにバージョン11にすることにしました。

　Heroku でバージョンを指定して PostgreSQL を導入する方法については、こちらのブログの記事を参考にさせて頂きました。（ありがとうございます。）
　　→　[[heroku]herokuのPostgreSQLでバージョンを指定する](http://kayakuguri.github.io/blog/2015/03/04/heroku-postgres-version/ "[heroku]herokuのPostgreSQLでバージョンを指定する")

##Netlify によるフロントエンドの公開

>・続けてフロントエンドを Netlify で公開します。いくつかの設定ファイルを追加しましょう。

（つづく）
Pythonで任意のクラスにmapとto_listを実装する(プライベート用)

# これめんどくさくない？

いきなりですがPythonの仕様上こう書くのってめんどくさくないですか？

```Python
list(map(lambda x: x + 1, [0, 1, 2])) # => [1, 2, 3]
```

あとから，listで括りなおすのとかmapの引数が先に関数なのとか，わりとややこしいように思います。

つまり他の言語みたいに，下のように書きたい！

```Python
[0, 1, 2].map(lambda x: x + 1).to_list() # => [1, 2, 3]
```

これをやるためのいい方法を見つけてしまったので記事にします(**きちんとした開発には不向きな方法なので，個人的な範囲での利用をオススメします**)。

# classにメソッドを追加できないの？

Pythonではclassにメソッドを追加するための方法として、次のような方法があります、

```Python
# クラスを定義しインスタンスを生成
class Bomb:
    pass
my_bomb = Bomb()

# 追加したいメソッドを関数として定義しクラスのプロパティに追加
def explosion(self):
    print("大爆発!")

Bomb.explosion = explosion

# 追加したメソッドが生成済みのオブジェクトからも利用できる
my_bomb.explosion()  # => 大爆発!
```

この方法は自分で定義したclassであればうまくいきますが。list, object等の組み込みclassではうまく行きません。

```
object.to_list = lambda self: list(self)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-9c86e5ed31fa> in <module>()
----> 1 object.to_list = lambda self: list(self)

TypeError: can't set attributes of built-in/extension type 'object'
```

# forbiddenfruitを使う
そこでforbiddenfruitを使います。名前の通り、禁断の果実なので、あまり多用しないように笑

```
pip install forbiddenfruit
```

としたのち、

```python
from forbiddenfruit import curse

def to_list(self):
    return list(self)

curse(object, 'to_list', to_list)
```
とすることで、任意のobjectにto_listメソッドが実装されます。
同様に

```python
curse(object, 'map', lambda self, f: map(f, self))
```
とすることで、mapメソッドが実装されます。

すると、

```python
[0, 1, 2].map(lambda x: x + 1).to_list() # => [1, 2, 3]
```
となり成功です。ただし、もとからto_listやmapなどが実装されている場合、どうなるかわかりませんので、objectではなく、もっと限られたクラスで実装すべきだとはおもいます(iterableのbase classってないよね？)
Nextjsプロジェクトのディレクトリ構成例をさらしてみる

## はじめに

今までreact単体のSPA構成でやっていたものの、webpackとかbabelの設定を試行錯誤しながら構築するのが面倒になったので、これを機にNextjsでスパッと構築できるようにテンプレートを作成しています。

その過程でディレクトリ構成を整理したので一例として共有します。

## ディレクトリ構成

```text
project_root/
├── docs/
├── public/
├── src/
│   ├── api/
│   │   ├── generated/
│   ├── components/
│   │   ├── atoms/
│   │   ├── molecules/
│   │   ├── organisms/
│   │   └── templates/
│   ├── foundations/
│   ├── hooks/
│   ├── lib/
│   ├── pages/
│   ├── stores/
│   ├── styles/
│   └── utils/
└── types/
```

- docs/

  ```text
  ドキュメントを配置する。
  仕様書やOpenApi定義もここに配置する。
  ```

- public/

  ```text
  静的ファイルを配置する。
  Nextjsで定義されたディレクトリ。
  ```

  see: <https://nextjs.org/docs/basic-features/static-file-serving>

- src/api/

  ```text
  WebApi等の外部APIのクライアントを配置する。
  自動生成されたApiのラッパーを作る時もここに配置する。
  ```

- src/api/generated/

  ```text
  OpenApi Generator等で自動生成されたクライアントを配置する。
  ```

- src/components/

  ```text
  UIコンポーネントを配置する。
  Atomic Designの分類に基づいてコンポーネント振り分ける。
  ```

- src/components/atoms/

  ```text
  部品となる汎用UIコンポーネントを配置する。
  単体で存在できるUIならここに配置する。
  ```

- src/components/molecules/

  ```text
  複数のUIコンポーネントを組み合わせたUIコンポーネントを配置する。
  特定のコンテキストに依存しないようして再利用を考慮する。
  UI制御のロジックが必要であればhooksを提供する。
  ```

- src/components/organisms/

  ```text
  特定のコンテキストに依存したUIコンポーネントを配置する。
  再利用はあまり考えなくてもいい。
  storesやapiに密結合していてもいい。
  ```

- src/components/templates/

  ```text
  ページ全体のスケルトンになるUIコンポーネントを配置する。
  ページのアクセス制御やレイアウト等を含んだコンポーネント。
  ```

- src/foundations/

  ```text
  UIに直接関係しない機能のみのコンポーネントを配置する。
  デザインを含まなければ、汎用的でもコンテキストに密結合でもどちらでもいい。
  ```

- src/hooks/

  ```text
  汎用的なreact hooksユーティリティを配置。
  特定のコンテキストに依存しないようにする。
  ```

- src/lib/

  ```text
  モジュール化されたロジックを配置する。
  lib間は依存してもいい。
  それ以外のレイヤーには依存しないようにする。
  ```

- src/pages/

  ```text
  Nextjsでルーティングされるページコンポーネントを配置する。
  ```

  see: <https://nextjs.org/docs/routing/introduction>

- src/stores/

  ```text
  グローバル状態を管理するhooksを配置する。
  ```

- src/styles/

  ```text
  全体のスタイルを配置する。
  テーマや汎用的なスタイル要素を定義する。
  ```

- src/utils/

  ```text
  ユーティリティロジックを配置する。
  ```

- types/

  ```text
  typescriptのカスタム型定義を配置する。
  ```

## おわりに

あくまで一例なのでプロジェクトに合わせて足したり引いたりしてください。
ディレクトリの定義も自分はこうしているというだけなので一番しっくりくるようにいい塩梅でやってください。

あと、**Nextjsはいいぞ！**
react単体だとCode Splittingとか色々頑張ってパフォーマンス調整をしていたのにNextjsは適当に作ってもだいたい速い。
あとSSGに方向を振ったおかげでSPA用のビルド環境として使えるのが強い。

まだSSRのフレームワークとして認知されているので導入提案しても最初はえぇ・・・？みたいな反応をされることもあるかと思います。
そんな時は圧を込めて**Nextjsはビルドツールです！！！**と言い張りましょう。
【PHP】初中級者が解くべき過去問精選 100 問を解いてみた【4問目/100】

アルゴリズムのアウトプット

ということで、
[レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編：目指せ水色コーダー！】](https://qiita.com/e869120/items/eb50fdaece12be418faa#2-3-%E5%88%86%E9%87%8E%E5%88%A5%E5%88%9D%E4%B8%AD%E7%B4%9A%E8%80%85%E3%81%8C%E8%A7%A3%E3%81%8F%E3%81%B9%E3%81%8D%E9%81%8E%E5%8E%BB%E5%95%8F%E7%B2%BE%E9%81%B8-100-%E5%95%8F)@e869120さん



>AtCoder で水色コーダー、つまりレーティング 1200 を少ない問題数で達成するために、茶色コーダー・緑コーダーにとって適切な教育的良問を 100 問集めました。

こちらの記事の初中級者が解くべき過去問精選 100 問
をPHPで解いていきます。

```php
<?php
$input_line = trim(fgets(STDIN));
$input_line = str_replace(array("\r\n","\r","\n"), '', $input_line);
$input_line = explode(" ", $input_line);
$arr = [];
for ($i = 0; $i < $input_line[0]; $i++) {
    $s = trim(fgets(STDIN));
    $s = str_replace(array("\r\n","\r","\n"), '', $s);
    $s = explode(" ", $s);
    $arr[] = $s;
}
$sumArr = [];

for ($k = 0; $k < $input_line[1]; $k++) {
    for ($l = 0; $l < $input_line[1]; $l++) {
        if ($k <= $l) {continue;}
        $sum = 0;
        for ($j = 0; $j < $input_line[0]; $j++) {
            $sum = $sum + max($arr[$j][$k], $arr[$j][$l]);
        }
        $sumArr[] = $sum; 
    }
}
echo max($sumArr) . "\n";
}
```
配列でデータを持って条件に合わせて参照する問題。
GitHubとSlackを連携させて通知を受けとるためのコマンド集

[Slackの公式](https://slack.com/intl/ja-jp/help/articles/232289568-GitHub-%E3%81%A8-Slack-%E3%82%92%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%8B)にも情報は載っていますが、よく忘れるので基本的なコマンドや通知機能の一覧を備忘録としてまとめておこうと思います‪‪。

# GitHub × Slack連携するための基本的なコマンド
通知 / 解除させたいSlackチャンネルで下記のコマンドをPostします。

### リポジトリ連携 / 連携解除する

```
/github subscribe owner/repository
/github unsubscribe owner/repository
```

`owner`と`repository`には対象とするGitHubリポジトリのオーナー名、リポジトリ名をそれぞれ指定します。

### 通知機能を購読 / 購読解除する

```
/github subscribe owner/repository [feature]
/github unsubscribe owner/repository [feature]
```

`[feature]`に指定できる通知機能の一覧は[この記事の下の方](https://qiita.com/drafts/fdfb2c5fe91ca6815d9c/edit#%E9%80%9A%E7%9F%A5%E6%A9%9F%E8%83%BD%E3%81%AE%E4%B8%80%E8%A6%A7)にまとめています。

### 全ての機能を購読したい場合

```
/github subscribe owner/repository issues,pulls,releases,deployments,reviews,comments,branches,commits:all
```

### 現在購読しているリポジトリの機能のリストを表示する

```
/github subscribe list features
```

# 通知機能の一覧

`[feature]`に指定できる通知機能の一覧です。

|feature|説明|デフォルト通知|
|---|---|:-:|
|issues|issueのオーブン / クローズ|◯|
|pulls|PRの作成 / マージ|◯|
|statuses|プルリクエストのStatus|◯|
|commits|default branchに対するコミット|◯|
|deployments|deploymentsステータスの更新|◯|
|public|リポジトリのpribateからpublicへの変更|◯|
|reviews|PRのレビュー|×|
|comments|PR / issueのコメント|×|
|branches|branchの作成と削除|×|
|commits:all|全てのブランチに対するコミット|×|
|+label:my-label|指定したラベルのissue、PR、コメント|×|

# 参考
https://slack.com/intl/ja-jp/help/articles/232289568-GitHub-%E3%81%A8-Slack-%E3%82%92%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%8B
XAMPPの環境設定でFound Path: " " -k runservice  Expected Path: " " -k runservice とエラーが出た時の対処法

# はじめに
Windows環境でXAMPPの環境構築をした時にハマった内容と解決した方法をまとめます。

# 環境
Windows 10
XAMPP 8.0.1

# ハマった内容
XAMPPで環境構築をしたところ、Apache,mysqlともに下記エラーが出て使えない。

![スクリーンショット 2021-01-24 13.20.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/678d015c-5bcd-6777-4fcd-e8ad86478f0e.png)

# やってみたこと
以前（私以外の方が）ApacheとMySQLを同PCにインストールして使っていたようで、
アンインストールがしっかりされているかの確認と対象ファイルの削除をした。
しかし、エラーの表示内容は変わらずだった。


# 参考にしたページ
https://stackoverflow.com/questions/30547759/apache-service-detected-with-wrong-path/52457073
>![スクリーンショット 2021-01-24 13.25.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/2a1173af-0a81-25a8-3a4b-65970f9361cc.png)

# 解決した方法
コマンドプロンプトで下記実行しました。

```
C:¥WINDOWS¥system32>sc delete Apache2.4
C:¥WINDOWS¥system32>sc delete MySQL
```
結果的にこれで問題が解決しました。

# まとめ
どうやらアンインストールしてもファイルが残ってたようです。
無事にXAMPPが使えるようになりました。
メキシコの方に感謝します。
refileで画像を複数投稿したい！

今回はrefileで画像を複数投稿できる機能を作ります。
調べたところ、画像複数投稿には　gem 'carrierwave'を使用する記事がたくさん出てきましたが、うまくいかなかったので今回はrefileで実装してみました。

##画像投稿用のテーブルを作成
画像１枚だけの投稿だと、対象のモデルにimageカラムを追加するだけでいいのですが、複数枚となると別でテーブルを作成する必要があります。

私はpet_imageモデルを新規作成しました。

```rudy
 create_table "pet_images", force: :cascade do |t|
    t.integer "pet_id"
    t.string "image_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["pet_id"], name: "index_pet_images_on_pet_id"
  end
```

##リレーションを組む
１：Nの関係性を持たせます。

```rudy:pet.rb
 has_many :pet_images, dependent: :destroy
 accepts_attachments_for :pet_images, attachment: :image
```

```rudy:pet_image.rb
 belongs_to :pet
 attachment :image
```

##コントローラーを編集

```rudy:pet.controller.rb

 private
 def pet_params
    params.require(:pet).permit(:name, :birthday, :gender, :introduction, :genre_id, :prefecture_id, :age, :is_active, :image,  pet_images_images:[] )
  end
```

##新規投稿フォーム編集

```rudy:pet.new.html
<%= form_with model: @pet, url: pets_path, method: :post, local: true do |f| %>
  <%= f.attachment_field :pet_images_images, multiple: true %>
<% end %>
```

##ペット一覧には画像を一枚だけ表示させたいので以下のように記述

```rudy:pet.index.html
  <% pet.pet_images.first(1).each do |image| %>
   <%= attachment_image_tag image, :image, size: '200x200' %>
  <% end %>
```

##画像を複数枚表示させたいところには↓

```rudy:pet.show.html
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script>
 <div id="slider">
   <% @pet.pet_images.each do |image| %>
      <%= attachment_image_tag image, :image, size: '350x350', class: "rounded mt-4" %>
   <% end %>
 </div>
```

##プラスでスライドショーにする:smile:

```rudy:application.html
<head>
  <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.css"/>
  <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.css"/>
</head>
```

```rudy:application.js
$(function() {
  $('#slider').slick({
      dots: true, 
      autoplay: true, 
      autoplaySpeed: 4000, 
  });
});
```

```rudy:application.css
.slick-next {
    right: 10px 
    z-index: 100;
 }

.slick-prev {
    left: 10px 
  z-index: 100;
 }
```

以上です！！
Laravel8 + React + web audio API で音を出す

# 目的
素人向けの記事がなかったので作成。
webで音声周りでやりたいことができたのでweb audio APIを使う。
この記事で公開されている[「Web Audio APIで単一サウンドを再生」](https://blog.howtelevision.co.jp/entry/2017/05/12/133546)を行う。

(※) サーバー周りをまだ試していないのでLaravelの解説はしない。あくまで動いたよ！という報告だけ。

# 前提

- Laravel8 + ReactでExample.jsを表示できたよ！という状態


# 手順
まずはnpmでインストール。しようとしたが、以下のようなエラーが出る。

```terminal
$ npm install react-webaudio
```

``` 
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: XXXXXXXXXXXXXXXXX@undefined
npm ERR! Found: react@16.14.0
npm ERR! node_modules/react
npm ERR!   dev react@"^16.2.0" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@"0.14.0" from react-webaudio@0.3.0-EXPERIMENTAL
```
Laravel uiのReactバージョンが16.14.0でweb Audioで要求されているバージョンが16.2.0だよ！ということらしい。
マイナーバージョンの差だし大丈夫でしょ！
動かなかったら考える理論で強制インストール。
ダメだった場合はバージョンを指定してReactをインストールし直しましょう。

```terminal
$ npm install --legacy-peer-deps react-webaudio
```
今回は音を鳴らすだけなので上記の記事を参考に、少し改変して Example.jsを以下のように修正。

``` Example.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Button} from '@material-ui/core';

const audioController = (() => {
    const context = new AudioContext();
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    const channels = 2;
    const frameCount = audioCtx.sampleRate * 2.0;
    const buffer = audioCtx.createBuffer(channels, frameCount, audioCtx.sampleRate);
  
    for (let channel = 0; channel < channels; channel++) {
      const nowBuffering = buffer.getChannelData(channel);
      for (let i = 0; i < frameCount; i++) {
        nowBuffering[i] = Math.random() * 2 - 1;
      }
    }
    const source = audioCtx.createBufferSource();
    source.buffer = buffer;
    source.connect(audioCtx.destination);
    source.start();
});

function Example() {
    return (
        <div className="container">
            <div className="row justify-content-center">
                <div className="col-md-8">
                    <div className="card">
                        <Button onClick={audioController}>On</Button>
                    </div>
                </div>
            </div>
        </div>
    );
}

export default Example;
if (document.getElementById('app')) {
    ReactDOM.render(<Example />, document.getElementById('app'));
}
```
コツは必ずアロー関数で宣言することである。

ビルドしたあとは画面に表示された「On」をクリックして「サーッ」と音が鳴ればOK。
色々できそうなAPIなので触って試してみたい。

## 追記(2020/2/4)

material-ui を追加していない場合はインストールしましょう

```terminal
$ npm install @material-ui/core
```
マイコーディングルーティン

<h2>はじめに</h2>
制作会社を通して作業前に確認する必要があることを備忘録として簡単にまとめました。


<h2>スケジュール・仕様確認</h2>
・納期
・サーバーは自社で作成　or　提供か
・サイトマップ,ディレクトリ構造
・新規or既存サイトの有無（記事の流用もあるのか）
・更新の可能性のある場所
・動的、静的、フォームの有無、その他ソース提供
・システム導入（スクラッチ or  WP or その他CMS）
・ブラウザ対応どこまで
・インクルード 
・ブレイクポイント(間の調整)
・ディスクリプションなどのメタタグ
・SNS アカウント、ogpタグ
・デザイン校了しているか

<h2>デザイン</h2>
・画像書き出し(pc,sp用)
・フォント設定（できれば特殊なフォントはなしにしてもらう。）
・可能な限りないフォントはDL。有料だったり、どうしてもない時は相談・もらう。
 ・サイズ、テキスト関連(フォントサイズ、字間、太さ、フォントの種類と有無)
・画像(Img)なのか背景(bg)にする部分と画像の形式
・サイトの動き、アニメーション（ボタンや各セクションのアニメーション）

<h2>コーディング</h2>
・コーディングルール(インデント、命名規則、レスポンシブ、SEO、アクセシビリティなど)
※READMEを用意しておくと共有が早い
・画像圧縮
・ SEO,アクセスビリティ( role属性入れる)
お客さん側で更新するもの（newsやblog,商品登録系)で文字数が長くなったときのレイアウト調整も視野に入れる。

<h3>◎複数で作業することも考えて</h3>
・ルール共有(css/FLOCCSS＋BEM,gulp)
・FTP接続情報共有
・git ・・・ github/gitrub /backlog
・画像圧縮
・ディレクトリの作成（jsやcss,htmlファイルの作成の方法）
・ボタンのホバー、クリックイベント
・静的と動的
※工数やサイトの規模などによりルール変動あり。

<h2>チェック</h2>
・デザイン確認（jpgで書き出したものやperfectPixel利用)
　※できたらデザイン作成者にみてもらう
・レイアウトやアニメーションのチェック
・ソースチェック（html/css検証サイトで確認）
・更新性のあるテキストや画像のレイアウトチェック
・各種リンクチェック
・各ブラウザ、タブレット、スマホでの確認
・アニメーションやjs部分の挙動確認

<h2>さいごに</h2>
適宜気づいたことや仕様の変更などあれば追記・修正します。
続き：bubbleのページ間で値をキャッチボールする方法


https://qiita.com/yoshio_y/private/419e0bc1c339860cd409
の続きとして下記部分ご説明していきます。

##解説ページの「次の問題へ」ボタンをクリックすると<br>問題ページへ遷移し問題番号が増える(１→２など）

![スクリーンショット 2021-01-24 14.50.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276430/4ed9b7c0-92ad-c5eb-2da2-416daa370048.png)

index(問題ページ）からanswer_page（問題解説ページ）に「第ｎ問」の情報を送り、
answer_pageで「第ｎ問の解説」として表示させる。
までは前回の記事でできたので、
今度はanswer_pageの「次の問題へ」Buttonを押す→問題ページの「第ｎ問」の数字が
カウントアップ「ｎ＋１」してあげるようにしましょう。

answer_pageのWorkFlowの設定は下記のようにします。

![スクリーンショット 2021-01-24 14.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276430/8a3462ec-f3c2-03aa-fe15-bf2686b064bc.png)

まずは「次の問題へ」Buttonを押すと、index（問題ページ）に遷移する設定をします。
次に、「Send more parameters to the page」のタブにチェックを入れ、
「Key」に「no」を、「＝」の先のValueには「Text A’ｓ QuizNumber」を入力します。

これでanswer_pageの処理は完了です。
（前回の記事の内容読んでいただければ、どういう処理してるか説明しているので割愛します）




**最後に、index（問題ページ）で「第ｎ問」の問題番号を「ｎ＋１」しましょう。**

indexページに遷移したとき（ページが読み込まれたとき）の処理を設定します。
![スクリーンショット 2021-01-24 15.59.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276430/b3e3bc4b-17b2-7ec4-43ab-552345990e60.png)
内容的には前回と一緒です。
処理としては、このページが表示された際に
「Text A」の「QuizNumber」というStateに、前のページから送られた
「no」という「Key」の中の数字を入れてあげます。
一つ付け加えると、初回のページロード時に
この処理はできないので（試してないですがエラー吐くかもなので）
「Only when」のところに「Get no from page URL is not empty」としてます。
内容としては、
遷移前のページから送られて来た「no」が、無い状態でないときこの処理をする
といった感じでしょうか。

ですが、このままでは「ｎ＋１」にならないので次の処理を設定します。
![スクリーンショット 2021-01-24 16.08.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276430/f972e728-32fc-0777-c1d4-8b5379882196.png)

「Text A」のstate「quiz number」のvalueに「＋１」します。

これでこのページがロードされるたびに「ｎ＋１」されていきます。
初回「第１問」の場合は「０＋１」して表示するのでDefault valueを「０」としてます。
![スクリーンショット 2021-01-24 10.22.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276430/dad9766f-cd12-d5e6-6b4e-968a2a621118.png)

以上、プレビューページで確認すると動きがカッコ悪いですが
もっとスマートな設定方法あればご教授ください！！！！
DiscordWebhookにbashのcurlでPOSTする


毎回400になるので

# 実行
```bash
curl -s -X POST -H 'Content-Type: application/json' -d {"content": '\""$MESSAGE"\"'}' $WEBHOOK_URL
```

# $MESSAGE
```bash
MESSAGE=`cat input.txt | sed "s/'//g" | perl -pe 's/\n/\\\\n/g' | sed "s/\"//g"`
```

- クオーテーション削り
- 改行ねじこみ
- `\"`の並びは削る

# $WEBHOOK_URL

```bash
WEBHOOK_URL=https://discordapp.com/api/webhooks/hogehoge-hogehoge
```
matlabでBLEを使う⑦SwitchBot温湿度計

　[「SwitchBot 温湿度計 デジタル スマート家電 高精度 スイス製センサー スマホで温度湿度管理 アラーム付き グラフ記録 アレクサ、Google home、HomePod、IFTTT に対応(ハブ必要)」](https://www.amazon.co.jp/gp/product/B07L4QNZVF/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1)
が安価に入手できます。ここでは、BLEで温度と湿度を読み取ります。
![IMGP0112.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/c86db6d2-306e-a6f2-29d5-7f56071b3303.png)

###UUIDなどを知る手順
　手順は、[matlabでBLEを使う④SHT31-SMART-GADGET](https://qiita.com/jamjam/items/d67d06edbca8c03acccb)と同じです。取得したアドレスはD6D36EEF4BA2でした。同様に、サービスUUIDとキャラUUIDも取得します。次のGitHubにもUUIDが書かれています。
　　https://github.com/OpenWonderLabs/python-host/wiki/Meter-BLE-open-API#0x30_Setting_Temperature_Display_Mode
　この資料から、

 - 0x57　Magic Number
 - 0x0f　拡張コマンドを送るよ
 - 0x31　ペイロード；Read the Display Mode and Value of the Meter

の3バイトを送りnotifyにすると、温度と湿度を送り返してくれます。送られてくるのは、次の4バイトです。

 - ステータス　1 – OK
 - 温度の小数点部分　0~9の数値
 - 温度　MSBは符号、残りが0~127℃の数値
 - 湿度　整数0~99

###プログラム
　温度は零下を無視しています。10秒ごとに10回測定します。

```matlab
clear
scan = blelist("Timeout", 20);

SwitchBox_address = "D6D36EEF4BA2";
b = ble(SwitchBox_address);
%bb = b.Characteristics;

Bot_ServiceUUID            = "CBA20D00-224D-11E6-9FB8-0002A5D5C51B";
data_CharacteristicUUID    = "CBA20003-224D-11E6-9FB8-0002A5D5C51B";
command_CharacteristicUUID = "CBA20002-224D-11E6-9FB8-0002A5D5C51B";

c1 = characteristic(b, Bot_ServiceUUID, command_CharacteristicUUID);
c10 = characteristic(b, Bot_ServiceUUID, data_CharacteristicUUID);
subscribe(c10);

for i=1:10
    %% https://github.com/OpenWonderLabs/python-host/wiki/Meter-BLE-open-API
    write(c1, [0x57 0x0f 0x31], "withResponse");
    data = read(c10);
    humi = data(4)
    temp = str2double( bitand(data(3), 0b01111111) + "." + data(2) )
    pause(10);
end
```

　実行例です。計測途中で本体の上部を手のひらで囲っています。
![switch101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/81911ab7-6b59-cdc7-81a9-8f8f25468fd0.png)
【PHP】住所を都道府県/市区町村/それ以降に分ける

# 参考

この記事を作るにあたり、以下のサイトを大いに参考にしました。

[なるべく短い正規表現で住所を「都道府県/市区町村/それ以降」に分けるエクストリームスポーツ](https://qiita.com/zakuroishikuro/items/066421bce820e3c73ce9)
[PHP: preg_match - Manual](https://www.php.net/manual/en/function.preg-match.php)
[[PHP] preg_match の正規表現の中で日本語（マルチバイト文字）を使う «  Codaholic](https://codaholic.org/?p=1671)

# コード

```PHP:separate_address.php
<?php

/**
 * @param string $address
 * @return array
 */
function separate_address(string $address)
{
    if (preg_match('@^(.{2,3}?[都道府県])(.+?郡.+?[町村]|.+?市.+?区|.+?[市区町村])(.+)@u', $address, $matches) !== 1) {
        return [
            'state' => null,
            'city' => null,
            'other' => null
        ];
    }

    return [
        'state' => $matches[1],
        'city' => $matches[2],
        'other' => $matches[3],
    ];
}

var_dump(separate_address('京都府京都市東山区清水1丁目294'));
var_dump(separate_address('東京都府中市宮西町2丁目24番地'));

var_dump(separate_address('不正な住所'));

// 市より先がない
var_dump(separate_address('東京都府中市'));

// 市名に村が入ってるのでうまく分けられていない。今回は非対応
var_dump(separate_address('東京都東村山市本町1丁目2番地3'));

```

```bash
$ php separate_address.php
array(3) {
  ["state"]=>
  string(9) "京都府"
  ["city"]=>
  string(18) "京都市東山区"
  ["other"]=>
  string(16) "清水1丁目294"
}
array(3) {
  ["state"]=>
  string(9) "東京都"
  ["city"]=>
  string(9) "府中市"
  ["other"]=>
  string(24) "宮西町2丁目24番地"
}
array(3) {
  ["state"]=>
  NULL
  ["city"]=>
  NULL
  ["other"]=>
  NULL
}
array(3) {
  ["state"]=>
  NULL
  ["city"]=>
  NULL
  ["other"]=>
  NULL
}
array(3) {
  ["state"]=>
  string(9) "東京都"
  ["city"]=>
  string(6) "東村"
  ["other"]=>
  string(27) "山市本町1丁目2番地3"
}

```
phpMyAdmin 4.6.6 のWarning対処

同じような環境を何度も構築しては、phpMyAdminから警告がでるので、いい加減まとめる。
最新をソースからinstallすればいいんだけど、aptに慣れた体にはﾏｼﾞ無理・・。

# 環境

 - Ubuntu 18.04.5 LTS (Bionic Beaver)
 - Apache 2.4.29
 - MySQL 5.7.32-0ubuntu0.18.04.1 - (Ubuntu)
 - PHP 7.2.24-0ubuntu0.18.04.7
 - phpMyAdmin 4.6.6deb5ubuntu0.5



インポート/エクスポート回り2箇所でWarningがでるので対処。


# Warning in ./libraries/plugin_interface.lib.php#551

```php

Warning in ./libraries/plugin_interface.lib.php#551
 count(): Parameter must be an array or an object that implements Countable
```

php7.2から、count(null)に対して0ではなく、warningを返すようになったため。
/usr/hsare/phpmyadmin/libraries/plugin_interface.lib.php の551行目あたり

```/usr/share/phpmyadmin/libraries/plugin_interface.lib.php
if ($options != null && count($options) > 0) {
```

を、

```/usr/share/phpmyadmin/libraries/plugin_interface.lib.php
if ($options != null && count((array)$options) > 0) {
```

に修正。もう一箇所は、、

# Warning in ./libraries/sql.lib.php#613

```php
Warning in ./libraries/sql.lib.php#613
 count(): Parameter must be an array or an object that implements Countable
```

/usr/share/phpmyadmin/libraries/sql.lib.phpの、613行目あたり。

```/usr/share/phpmyadmin/libraries/sql.lib.php
  || (count($analyzed_sql_results['select_expr'] == 1)
```

を、

```/usr/share/phpmyadmin/libraries/sql.lib.php
|| ((count($analyzed_sql_results['select_expr']) == 1)
```



# 参考(ありがとう）
 - https://qiita.com/nanbuwks/items/2277dd308ddd0f1ee4dc
 - https://gyaboo.com/article.php?story=20190717104326948
pythonでAWSのリソース情報を取得してyamlファイルを編集してみた

#はじめに

仕事で特定のyamlファイルをコピーして、EC2のIPアドレスなどの特定の箇所を編集してplaybookを実行することがあり、手作業だとミスが起きると思いプログラムでAWSのリソースを取得して、その値でyamlファイルを書き換えられないか試してみた。

# 実施したこと

引数として

* 編集したいyamlのファイル名
* EC2のタグ(Name)の値
* AWSのプロファイル

を渡してあげて、AWSのプロファイルの設定で、EC2タグの値に紐づくECインスタンスを取得して
yamlファイルを編集する。

# yamlファイルのイメージ

```yaml
- hosts: target_test
  tasks:
  - name: install git
    yum: name=git state=latest
  instance:
    private_ip: 0.0.0.0
    public_ip: 0.0.0.0
    ip: 0.0.0.0

```
↑のprivate_ipと、public_ipを編集する。

# 作成したソース

```python
#!/usr/bin/python
# -*- coding: utf-8 -*-

import ruamel
import ruamel.yaml
import sys
import boto3
from boto3.session import Session

yaml = ruamel.yaml.YAML()

args = sys.argv
file_name = args[1]
tag_value = args[2]
profile = args[3]
# プロファイルの内容でAWSのリソースにアクセスするように設定
session = Session(profile_name=profile)

def read_file(file_name):
    """
    ファイル読み込み
    引数
    file_name: ファイル名

    返り値
    loadしたyamlデータ
    """
    with open(file_name, 'r') as file:
        data = yaml.load(file)

    return data

def fetch_ec2_instance(tag_value):
    """
    ec2インスタンス取得
    引数
    tag_value: ファイル名

    返り値
    Name=tag_valueのインスタンス
    """
    ec2 = session.client("ec2")

    # Nameタグでフィルター
    instances = ec2.describe_instances(
            Filters=[
                {'Name': 'tag-key', 'Values': ['Name']},
                {'Name': 'tag-value', 'Values': [tag_value]}
            ]
        )['Reservations']
    
    if len(instances) == 0:
        raise Exception("インスタンスが存在しません。 Name:{}".format(tag_value))
    
    return instances[0]

def edit_data(data, instance):
    """
    パブリックIP、プライベートIPの修正
    引数
    data: yamlデータ
    instance: ec2インスタンス
    """
    data[0]["instance"]["private_ip"] = instance['Instances'][0]['PrivateIpAddress']
    data[0]["instance"]["public_ip"] = instance['Instances'][0]['PublicIpAddress']

def write_data(file_name, data):
    """
    yamlデータ書き込み
    file_name:　書き込むファイル名
    data: yamlデータ
    """

    with open(file_name, 'w') as file:
        yaml.dump(data, stream=file)

data = read_file(file_name)
instance = fetch_ec2_instance(tag_value)
edit_data(data, instance)
write_data(file_name, data)
```

ruamelを使用して、yamlファイルの編集をしてます。
PyYamlもあるのですが、その場合yamlファイルの順序が保障されてないためruamelを使用してます。

以下コマンドで実行

```
python {pythonのソースファイル名} {編集ファイル名}  {Nameタグの値} {プロファイル}
```

# 参考

ruamelについて
https://dev.classmethod.jp/articles/getting-started-with-pyyaml-and-ruamel-yaml/

デフォルトのプロファイル以外を使用する
https://qiita.com/inouet/items/f9723d7ae7d8d134280b
ほんと、この手の問題解決は時間がかかる！ChromeのローカルホストでSSL証明書を信頼させる方法！！

今サイト制作を行っているのですが、Stripeを導入しサブスクリプションの決済を行おうとしているところ、下記のようなエラーが発生しました。

>SSL certificate is not valid. Security level: DANGEROUS. 

色々調べたところ、SSL証明書と言うものを発行し、Stripeに信頼させないといけないらしい。

この手の問題は本当に苦手。。。

とりあえず問題は解決できたので、その方法をおさらいしていきます！

#証明書のエクスポート#

まず、SSLの証明書を発行していない場合、ChromeのURLの部分に「安全なサイトではありません」的な内容が書かれていると思います。

また、URLを見てみると、``https``にボーダーが引かれています。

とりあえずURLの左側にある画像のようなマークをクリックします。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/e7b06bc3-8175-5cbf-3ca4-842a5667d036.png)


このようなまーマークが無い場合は、「安全なサイトではありません」クリックして見て下さい。

すると以下のような画面が現れると思います。

![無題.2png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/2946495a-ac2f-99ce-781b-501a161be570.png)


そして、SSLの証明が行われていないと、「証明書（無効）」と表れるはずです。

まずは、証明書をクリックしてください。

そして、「詳細」の欄をクリックし、「ファイルにコピー」をクリック。

![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/b09f348e-8e16-f269-d336-830e761b07ce.png)


次に、このような画面になるので、「次へ」をクリック。

![無題4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/5c2179ae-1af6-f2b9-f6a1-9588acb0bd82.png)


これも「次へ」クリック

![無題5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/c3d42c67-2b74-a5e7-bbd2-24668e137644.png)


そして、この画面になったら任意のフォルダを選択し、ファイル名を入力し「次へ」をクリック。

![無題6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/02b16df5-0331-b9b4-bedd-1e6988384eeb.png)


すると、選択したフォルダに証明書（.cer）が発行されていると思います。

#証明書をインポート#

最後に、発行した証明書をChromeにインポートします。

次に、設定を開きます。

![無題7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/375164b9-215b-8eb2-b294-9b748c9510e1.png)


少し下に行くと、このような欄があると思います。

![無題8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/b8ee3eb2-dd91-541b-6411-1892fb173be5.png)


そしてら、「セキュリティ」→「証明書の管理」→「信頼されたルート証明書期間」の順にクリックします。

![無題9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954754/a9f01a6d-d590-b63e-60b4-45b888dae9ea.png)


するとこのような画面になるので、「インポート」をクリック

「次へ」をクリック。

先ほど保存した証明書（.cer）を選択し「次へ」をクリック。

後は、全部「次へ」をクリックすると証明書がインポートされます。

そしたらクロームを再起動。

ローカルホストを立ち上げている場合も一旦止めます。

そしていつものようにローカルホストを起動してあげると、SSLのエラーが出なくなります！

これで結構時間食われたので、ぜひこの記事を参考にしてエラー解決してくれたらなと思います。

皆さんの勉強時間が潰されないことを祈っております。

以上、「ほんと、この手の問題解決は時間がかかる！ChromeのローカルホストでSSL証明書を信頼させる方法！！」でした！

良かったら、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
InfluxDBで遅行指標を作る

これで、２４時間前までの計算を終えた範囲を24時間先にずらすことで遅行指標として表示できる。
rangeの`stop: -24h`を消すと、24時間分、このグラフが先行して表示されるので、見栄えが悪い。

```sql
from(bucket: "XYZBucket")
  |> range(start: v.timeRangeStart, stop: -24h)
  |> timeShift(duration: 24h)
```
mac+vscode+vim設定でのカーソル移動・連打問題の解決

# 問題
- macのvscodeで、vimのキーバインドしたい。
- [vscodevim](https://marketplace.visualstudio.com/items?itemName=vscodevim.vim)プラグインをインストールしたが、hjklによるカーソル移動ができない。
- 正確に言うと、押しっぱなしで連続移動したいのに、連打する必要がある。

# 解決方法
vscodeのターミナルで以下のコマンドを実行して、vscode自体を再起動する。

```
defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false
defaults write com.microsoft.VSCodeInsiders ApplePressAndHoldEnabled -bool false
```
# 後書き
参考になる記事がすぐに見つかったため、時間をかけずに解決できました。今後ずっと連打かと思うとかなりのタイプに時間と体力を奪われることになるので、非常に助かりました。

# 参考記事
https://twismik0.hatenablog.com/entry/2017/08/14/115502
5分で学ぶ React Hooks

## この記事の目的
公式ページが Hooks がいかに素晴らしいかなどが書いてあって長いので、必要最低限な情報をまとめた。
これを読めば Hooks を知らない人でもレビューはできるようになるはず。（願望）
### Hooks とは
React 16.8 で追加された機能。
ステートフック、副作用フック、コンテキストフック、リデューサフックなどがある。
### Hooks のメリット
Class でゴリゴリ書かないといけないものが Function で書けるようになった。
シンプルに書ける、ボイラープレートを減らせる。
## 主に使うメソッド
### ステートフック(useState)
```useStete.js
const [a, setA] = useState(0)
```
使い方
`useState` の引数に初期値を渡す。
`a` には `get` が、`setA` には `set` の機能がある。
### 副作用フック(useEffect)
```useEffect.js
useEffect(() => {
  a();
  return () => {
    b();
  };
}, [c]);
```
`useEffect` の中の `a()` がライフサイクルの `componentDidMount` と `componentDidUpdate` で実行される。
`useEffect` の返り値の `b()` がライフサイクルの `componentWillUnmount` と `componentDidUpdate` で実行される。
`componentDidUpdate` は `b()` → `a()` の順番で実行する。

`useEffect` の第二引数を指定しなかった場合、上記のタイミングで実行されるが、指定した場合は指定した値が変わっていない場合には実行されないようにできる。上記例であれば `c` の値が更新された場合にのみ実行されるようになる。パフォーマンス改善の為に使う。
## 複雑な設計になった際に使うメソッド
ここから先はメソッドの存在と必要なタイミングについて軽く触れるだけ。
### コンテキストフック(useContext)
```useContext.js
const value = useContext(MyContext);
```
親コンポーネントで指定した値を子コンポーネントが `useContext` 経由で取得できる。子コンポーネントに値をいちいち渡さなくて良くなる。
https://ja.reactjs.org/docs/hooks-reference.html#usecontext
### リデューサフック(useReducer)
```useReducer.js
const [state, dispatch] = useReducer(reducer, initialArg, init);
```
`useStete` の変異種。`setXXX` だとどんな値でも入れられてしまう為、値の変更方法を指定して意図せぬ値の変更を防ぐ為に使用する。
https://ja.reactjs.org/docs/hooks-reference.html#usereducer
## まとめ
前に Redux を使ったがその時よりもシンプルにかけていい感じ。
自分で実装したい人は公式を読みましょう。
https://reactjs.org/docs/hooks-intro.html