[React]ボタン押下で動的にformを追加する

# ざっくり説明

1年前に下書きしてたやつを掘り返した。

やり方は大まかにこんな感じ。

* buttonをclickでformを追加
* formの内容がchangeしたときに値をsetState

# コード書くよ
## 前提として
ここから始まります。

```react
import React from 'react';

class TaskForm extends React.Component {
  constructor(props){
    super(props);
    this.state={
      tasks: [
        {
          task_name: "",
          start_datetime: "",
          end_datetime: "",
          task_memo: "",
        }
      ],
    };
  }

  render() {
    return (
      <div className="task-form">
          <input type="text" placeholder="task_name" name="task_name" value={task.task_name} />
          <input type="datetime-local" placeholder="start_datetime" name="start_datetime" value={task.start_datetime} />
          <input type="datetime-local" placeholder="end_datetime" name="end_datetime" value={task.end_datetime} />
          <textarea placeholder="task_memo" name="task_memo" value={task.task_memo} />
      </div>
    );
  }
}

export default TaskForm;

```
## 本題
### button追加
```react
  render() {
    return (
      <div className="task-form">
          <input type="text" placeholder="task_name" name="task_name" value={task.task_name} />
          <input type="datetime-local" placeholder="start_datetime" name="start_datetime" value={task.start_datetime} />
          <input type="datetime-local" placeholder="end_datetime" name="end_datetime" value={task.end_datetime} />
          <textarea placeholder="task_memo" name="task_memo" value={task.task_memo} />
          
          <button type="button" onClick={() => this.addNewTask()}>+</button>
      
      </div>
    );
  }
```
### addNewTask()記述
```react
  addNewTask(){
    this.setState({
      tasks: [...this.state.tasks,
      {
          task_name: "", 
          start_datetime: "", 
          end_datetime: "", 
          task_memo: ""
      }]
    });
  }
```
### map関数導入
```react
  render() {
    return (
      <div className="task-form">
        {
          this.state.tasks.map((task, index) => {
            return (
              <div key={index}>
                <input type="text" placeholder="task_name" name="task_name" value={task.task_name} />
                <input type="datetime-local" placeholder="start_datetime" name="start_datetime" value={task.start_datetime} />
                <input type="datetime-local" placeholder="end_datetime" name="end_datetime" value={task.end_datetime} />
                <textarea placeholder="task_memo" name="task_memo" value={task.task_memo} />
              </div>
            )
          })
        }
        <button type="button" onClick={() => this.addTask()}>+</button>
      </div>
    );
  }
```
## 入力した値を表示
### onChange
```react
  render() {
    return (
      <div className="task-form">
        {
          this.state.tasks.map((task, index) => {
            return (
              <div key={index}>
                <input type="text" placeholder="task_name" name="task_name" value={task.task_name} onChange={(e) => {this.handleChange(e, index)}}/>
                <input type="datetime-local" placeholder="start_datetime" name="start_datetime" value={task.start_datetime} onChange={(e) => {this.handleChange(e, index)}}/>
                <input type="datetime-local" placeholder="end_datetime" name="end_datetime" value={task.end_datetime} onChange={(e) => {this.handleChange(e, index)}}/>
                <input type="url" placeholder="url" name="url" value={task.url} onChange={(e) => {this.handleChange(e, index)}}/>
                <textarea placeholder="task_memo" name="task_memo" value={task.task_memo} onChange={(e) => {this.handleChange(e, index)}}/>
              </div>
            )
          })
        }
        <button type="button" onClick={() => this.addTask()}>+</button>
      </div>
    );
  }
```
### handleChange()
```react
  handleChange(e, index){
    this.state.tasks[index][e.target.name] = e.target.value;
    this.setState({tasks: this.state.tasks});
  }
```
# 参考

1年前で不確かだけど外国人の方のYoutubeです。
react dynamic form
とかで検索してたはず。
それっぽいのおいておきます。。。
参考にさせていただいた方すみません。

https://www.youtube.com/watch?v=sklFJF2wVWc