redux-formを使って自作APIにデータを送った

#概要
自分用勉強メモです。
redux-formを使ってみました。名前を入力してそのデータをjson-serverで作ったデータベースに送ってみたいと思います。

json-server公式
https://www.npmjs.com/package/json-server
#フォームを作る
名前を入力するフォームを作っていきます。
まず必要なライブラリをインストールします。

```terminal
npm install --save redux react-redux redux-form redux-thunk axios
```

データベースと非同期通信するのでredux-thunkとaxiosを取ってきます。
まずsrc/index.js

```javascript:src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';

import App from './components/App';
import reducers from './reducers';

const store = createStore(
  reducers,
  applyMiddleware(thunk)
);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
)
```
いつも通りの雛形です。
次にreducerをみてみます。

```javascript:src/reducers/index.js
import { combineReducers } from "redux";
import { reducer as formReducer } from 'redux-form';

export default combineReducers({
  form: formReducer
});
```
ここでredux-formからreducerを取っています。
reducerだとわかりにくいのでasを使ってformReducerとしています。
メインのApp.jsを見ていきます。

```javascript:src/components/App.js
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';

class App extends Component {
  renderInput({input}) {
    return (
      <div>
        <label>name</label>
        <input {...input} />
      </div>
    );
  }

  onSubmit = () => {
    //データベースと通信するアクションを書く
  }

  render() {
    return (
      <form onSubmit={this.props.handleSubmit(this.onSubmit)}>
        <Field name="name" component={this.renderInput} />
      </form>
    );
  }
}

export default reduxForm({
  form: "nameList"
})(App);
```
ここでredux-formからField, reduxFormを取っています。
見ればわかる通り、Fieldがフォームとなる部分になります。
FieldにはnameとcomponentがありますがnameはそのフォームをformValuesで参照することができます。
つまり、空白で送って欲しくないバリデーションをつけたい場合、上記の例では

```javascript
if (!formValues.name) {
  //エラーの時出したい処理
}
```
のようになります。
renderInput()のところにはformPropsがくるのですが、formProps.inputには便利なものがたくさん入っているので、それらを{...formProps.input}としてとるところを簡潔に{...input}と書いています。
気になればconsole.log(formProps);してみてください。
あとはhandleSubmitのメソッドを使って送れるのでそこにjson-serverと通信するアクションを乗せてあげます。

その前に、データベースを作りましょう。
#データベースを作る

```terminal
mkdir api
cd api
npm init
npm install --save json-server
```
新たにディレクトリを作り、npm initでpackage.jsonを取得し、json-serverをインストールします。
apiフォルダを開いて必要なファイルを作ります。

```json:db.json
{
  "nameList": []
}
```
送ったデータを配列で管理するようにします。
次にpackage.jsonを少しいじります。

```json:package.json
{
  "scripts": {
    "start": "json-server -p 3001 -w db.json"
  }
}
```
"scripts"のところを上記のようにします。
3001のポートでdb.jsonを参照するというコードです。
最後にnpm startでapiを起動しましょう。
#仕上げ
次にaxios.createを使ってベースを作ります。

```javascript:src/apis/nameList.js
import axios from 'axios';

export default axios.create({
  baseURL: "http://localhost:3001"
});
```
そのままアクションも作りましょう。

```javascript:src/actions/index.js
import nameList from '../apis/nameList';

export const submitName = (formValues) => async (dispatch) => {
  await nameList.post('/nameList', formValues)
};
```
postを使って入力された文字を送信するアクションです。postの第一引数にはdb.jsonで書いた配列のキーが入ります。
最後にApp.jsで仕上げます。

```javascript:src/components/App.js
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { submitName } from '../actions';

class App extends Component {
  renderInput({input}) {
    return (
      <div>
        <label>name</label>
        <input {...input} />
      </div>
    );
  }

  onSubmit = (formValues) => {
    this.props.submitName(formValues);
  }

  render() {
    return (
      <form onSubmit={this.props.handleSubmit(this.onSubmit)}>
        <Field name="name" component={this.renderInput} />
      </form>
    );
  }
}

const formWrapped = reduxForm({
  form: "nameList"
})(App);

export default connect(null, { submitName })(formWrapped);
```
これでフォームに何か入力してエンターを押すとデータベースに保存されるはずです。
デベロッパーツールのネットワーク、ターミナルでcat db.jsonで送った内容が保存されてidが付いていると思います。
#まとめ
今回はredux-formを使ってみました。
まだまだわからないことが多いので知識を蓄えていきたいと思います。
参考になれば幸いです。