制御コンポーネントの作成

# Inputフィールドの作成

コンポーネントを一通り学んだ後に簡単なInputフィールドを作って遊んでみました。
しかし、意外と簡単にはいかず、良い復習になったので備忘録を残しておきます。

## 簡単な書き方

こんな感じで書いてみました。
ブラウザから見るととりあえず動いています。

``` react
import React, { useState, useCallback, useMemo } from 'react';
import './App.css';

const App=()=> {
  return (
    <div className="App">
      <header className="App-header">
        <input type="text"/>
      </header>
    </div>
  );
}

export default App;
```

この場合、コンポーネントの状態 (state) を全く記述しておらず、入力の状態をどう保持するのかって感じです。
＊このようなコンポーネントを「**ステートレスコンポーネント (stateless component)**」と言うそうです。
また、値の状態がビューと切り離されておらず、アプリケーションの設計としては良いとは言えないです。

## stateの管理
Inputの値（value）を`state`で管理します。

```react
const App=()=> {
  const [message, setMessage] = useState('');
  return (
    <div className="App">
      <header className="App-header">
        <input type="text" value={message}/>
      </header>
    </div>
  );
}
```
`const [message, setMessage] = useState('')`で`state`を保持します。
- `message` .. state変数
- `setMessage` .. state変数の状態を変更するための関数

クラスコンポーネントは`this.state`と言う書き方で内部の値を保持することができましたが、関数コンポーネントでは同様の書き方はできません。そこで、Hookの`useState`を使ってあげて変数の状態を保持することを可能とします。

**参考）useState を呼ぶと何が起きるの？**
> これにより『state 変数』が宣言されます。useState は、クラスにおいて this.state が提供するのと全く同じ機能を実現するための新しい方法です。通常、関数が終了すると変数は『消えて』しまいますが、state 変数は React によって保持されます。

https://ja.reactjs.org/docs/hooks-state.html

これで再度ブラウザから動きを確認します。。。
何も入力できないことが分かります。

## stateの変更
ここで公式ドキュメントの`useState`を再度確認します。
`useState`は「**state変数とstate変数の状態を変更するための関数**」を返します。
2つ目の戻り値と言うのが「state変数の状態を変更するための関数」であり、言い換えると「**state変数の状態を変更したい場合はこの関数を呼ぶ**」と言うことです。これをしっかりと理解していないと上のようなことが起きてしまいます。

カウントダウンのような機能の場合、関数コンポーネント内に以下のように書きます。

```react
const [count, setCount] = useState(0);

<button onClick={() => setCount(count + 1)}>
```

messageの状態を変更するための関数`setMessage`を定義を呼び出すための関数（ハンドラ）を定義し、inputフィールドの`onChanged`属性に指定します。

```react
const App=()=> {
  const [message, setMessage] = useState('');
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMessage(e.target.value);
  };
  return (
    <div className="App">
      <header className="App-header">
        <input type="text" value={message} onChange={handleChange} />
      </header>
    </div>
  );
}

```

これでやりたいことは実現できます。

このようなにコンポーネントの内容をstateの状態で保持するものを制御コンポーネントと言うみたいです。

## コンポーネントの分割
おまけにコンポーネントの分割も試してみます。
今回は簡単のため、`App`コンポーネントにinputフィールドを記述しました。
inputフィールドが１つの場合は良いかもしれないですが、複数の場合はコンポーネントの分割を検討するのが良いかもしれません。

こんな感じで`InputText`のコンポーネントを作ってみました。
`InputText`が受け取る引数を`Props`で定義しておきます。

```react
import React from 'react';
import styled from 'styled-components';

const Input = styled.input`
  height: 60px;
  width: 450px;
  border: 1px solid #BEBEBE;
  box-sizing: border-box;
  border-radius: 6px;
  padding-left: 16px;
  font-size: 24px;
  color: #222222;
  ::placeholder {
    color: #C1C1C1;
  }
`;

type Props = {
    value: string,
    onChange: (e: React.ChangeEvent<HTMLInputElement>) => void,
    placeholder: string,
};
  
const InputText = (props: Props) => {
  const {
    value,
    onChange,
    placeholder,
  } = props;
  return (
    <Input
      type=""
      value={value}
      placeholder={placeholder}
      onChange={onChange}
    />
  );
};
  
export default InputText;
```

これを`App`コンポーネントで呼び出してあげます。

```react
import React, { useState, useCallback, useMemo } from 'react';
import logo from './logo.svg';
import './App.css';

import InputText from './components/elements/inputText';

const App=()=> {
  const [message, setMessage] = useState('');
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMessage(e.target.value);
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <InputText
            value={message}
            placeholder="ID"
            onChange={handleChange}
        />
      </header>
    </div>
  );
}

export default App;

```

こんな感じで簡単にコンポーネントの分割が実現できました。