React.js & Next.js超入門のチャプター６を改変：Firestore使用するようにした②

#React.js & Next.js超入門のチャプター６を改変：Firestore使用するようにした②

<a target="_blank"  href="https://www.amazon.co.jp/gp/product/B07X7DHZ9F/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B07X7DHZ9F&linkCode=as2&tag=kokkahasan-22&linkId=dd5df6fbbe94454250a9b9130edc29c1"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=B07X7DHZ9F&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=kokkahasan-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&l=am2&o=9&a=B07X7DHZ9F" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a target="_blank" href="https://www.amazon.co.jp/gp/product/B07X7DHZ9F/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B07X7DHZ9F&linkCode=as2&tag=kokkahasan-22&linkId=73249152ab7e0fd9cf8875e18987c25d">React.js &amp; Next.js超入門</a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&l=am2&o=9&a=B07X7DHZ9F" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

はなかなか良い本なのだが、最後のチャプター６「Firebaseでデータベースを使おう」でFirestoreでなくRealtime Databaseを使ってる。なので買うのを躊躇した人いるかもと思ってFirestoreを使用するコードに変えてみた。

[React.js & Next.js超入門のチャプター６を改変：Firestore使用するようにした①](https://qiita.com/atomyah/items/98518b84c5bbd627865b)からのつづき、
セクション6-2

####▼リスト6-6 store.js
Firebaseへの接続情報を`.config.js`に逃がすので以下のように変更（理由は.gitignoreに.config.jsを記述したいため）

```jsx
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import firebase from "firebase";
import "firebase/firestore"; 
import { firebaseConfig } from './.config';

// Firebaseの設定. initializeApp()は一度だけ実行させたいので、一度だけ呼ばれるstore.jsに記述する.
try {
  firebase.initializeApp(firebaseConfig);
} catch (error) {
  console.log(error.message);
}
const db = firebase.firestore();
export { db };


//// 以下はRedux処理.あくまで参考でここでは使用していない.
// ステート初期値
const initial = {
}

// レデューサー（ダミー）
function fireReducer(state = intitial, action) {
  switch (action.type) {
    // ダミー
    case 'TESTACTION':
      return state;
    // デフォルト
    default:
      return state;
  }
}

// initStore関数
export function initStore(state = initial) {
  return createStore(fireReducer, state, 
    applyMiddleware(thunkMiddleware))
}
```

プロジェクトルートに`.config.js`ファイルを作成し以下のように。

```jsx
export const firebaseConfig = {
  apiKey: " APIキー ",
  authDomain: "プロジェクト.firebaseapp.com",
  databaseURL: "https://プロジェクト.firebaseio.com",
  projectId: "プロジェクト",
  storageBucket: "プロジェクト.appspot.com",
  messagingSenderId: " ID番号 ",
  appId: ""
};
```

####▼リスト6-7 fire.js
本の通り

####▼リスト6-8 fire_find.js
本の通り

####▼リスト6-9 FireFind.js
以下の通り。import～の部分と、// 検索の実行コードを変更

```jsx
import React, {Component} from 'react'
import {db} from "../store";

class Firefind extends Component {
    style = {
      borderBottom:"1px solid gray"
    }
  
    // 初期化。ステートとイベント用メソッドの設定
    constructor(props) {
      super(props);
      this.state = {
        input:'',
        data:[]
      }
      this.doChange = this.doChange.bind(this);
      this.doAction = this.doAction.bind(this);
    }
  
    // 入力フィールドに入力時の処理
    doChange(e){
      this.setState({
        input:e.target.value
      })
    }
  
    // ボタンクリック時の処理
    doAction(e){
      this.findFireData(this.state.input);
    }
  
    // 検索の実行
    findFireData(s){
        db
          .collection("sample")
          .where("ID", "==", s)
          .get()
          .then(querySnapshot => {
              const items = querySnapshot.docs.map(doc => doc.data());
              this.setState({ data: items })
          });   
    }
  
    // テーブルの内容の作成
    getTableData(){
      let result = [];
      if (this.state.data == null || this.state.data.length == 0){
        return [<tr key="0"><th>NO DATA.</th></tr>];
      }
      for(let i in this.state.data){
        result.push(<tr key={i}>
          <th>{this.state.data[i].ID}</th>
          <th>{this.state.data[i].name}</th>
          <td>{this.state.data[i].message}</td>
        </tr>);
      }
      return result;
    }
  
    // レンダリング
    render(){
      return (<div>
        <input type="text" onChange={this.doChange}
          style={this.style} value={this.state.input} />
        <button onClick={this.doAction}>Find</button>
        <hr />
        <table><tbody>
          {this.getTableData()}
        </tbody></table>
      </div>)
    }
  }
  
    export default Firefind;
```

####▼リスト6-10 fire_add.js
本の通り

####▼リスト6-11 Fireadd.js
import～と、// 最後のIDを取得、および// データを追加する のコードを変更

```jsx
import React, {Component} from 'react'
import {db} from "../store";
import Router from 'next/router';

class Fireadd extends Component {
    style = {
      fontSize:"12pt",
      padding:"5px 10px"
    }
  
    // 初期化処理
    constructor(props) {
      super(props);
      this.state = {
        name_str:'',
        msg_str:'',
        lastID:-1,
        data:[]
      }
      this.getLastID(); // 最後のIDのチェック
      this.doChangeName = this.doChangeName.bind(this);
      this.doChangeMsg = this.doChangeMsg.bind(this);
      this.doAction = this.doAction.bind(this);
    }
  
    doChangeName(e){
      this.setState({
        name_str:e.target.value
      })
    }
    doChangeMsg(e){
      this.setState({
        msg_str:e.target.value
      })
    }
    doAction(e){
      this.addFireData();
      Router.push('/fire');
    }
  
    // 最後のIDを取得
    getLastID(){
        db
          .collection("sample")
          .orderBy('ID')
          .limitToLast(1)
          .get()
          .then(querySnapshot => {
              const items = querySnapshot.docs.map(doc => doc.data());
              console.log('itemsは■' + JSON.stringify(items));
              const itemID = items[0].ID; // 配列構造のJSONデータitemsからID部分だけをとりだす
              console.log('itemIDは■' + itemID);
                this.setState({
                    lastID:itemID
                  });
          });   
    }
  
    // データを追加する
    addFireData(){
        if (this.state.lastID == -1){
            return;
        }
        let id = this.state.lastID * 1 + 1; //ここで * 1 + 1の処理をしたことでidは数値型になった。
        console.log('idは■' + id);
        let stringed_id = String(id); // ここでString型にしないとFunction CollectionReference.doc() requires its first argument to be of type non-empty string, but it was:... エラー
        console.log('stringed_idは■' + stringed_id);
        const docRef = db.collection("sample").doc(stringed_id);
        docRef
          .set({
            ID: stringed_id,
            message: this.state.msg_str,
            name: this.state.name_str
          });           
    }
  
    // レンダリング
    render(){
      if (this.state.lastID == -1){
        this.getLastID();
      }
      return (<div>
        {(this.state.lastID == -1)
        ?
        <p>please wait...</p>
        :
        <table>
        <tbody>
          <tr>
            <th className="label">name</th>
            <td><input type="text" placeholder="your name."
              onChange={this.doChangeName}
              value={this.state.name_str} /></td>
          </tr>
          <tr>
            <th className="label">message</th>
            <td><input type="text" size="40"
              placeholder="type message..."
              onChange={this.doChangeMsg}
              value={this.state.msg_str} /></td>
          </tr>
          <tr><th></th><td>
          <button onClick={this.doAction}>Add</button>
          </td></tr>
        </tbody>
        </table>
        }
      </div>)
    }
  }
  
  export default Fireadd;
```

####▼リスト6-12 fire_del.js
本の通り

####▼リスト6-13 Firedelete.js
import～と、// 項目の削除 のコードを変更

```jsx
import React, {Component} from 'react'
import Router from 'next/router';
import {db} from "../store";

class Firedelete extends Component {
  style = {
    fontSize:"12pt",
    padding:"5px 10px"
  }

  // 初期化処理
  constructor(props) {
    super(props);
    this.state = {
      id_str:'',
    }
    this.doChange = this.doChange.bind(this);
    this.doAction = this.doAction.bind(this);
  }

  doChange(e){
    console.log('doChangeの中' + e.target.value);
    this.setState({
      id_str:e.target.value
    })
  }

  doAction(){
    this.deleteFireData();
    Router.push('/fire');
  }

  // 項目の削除
  deleteFireData(){
    let id = this.state.id_str;
    console.log('■id: ' + id);
    db
    .doc("sample/" + id)
    .delete()
    .then(() => {
        console.log('削除しました')
    })
  }

  // レンダリング
  render(){
    return (<div>
      <table>
      <tbody>
        <tr>
          <th className="label">ID:</th>
          <td><input type="text" placeholder="delete ID:"
            onChange={this.doChange}
            value={this.state.id_str} /></td>
        </tr>
        <tr><th></th><td>
        <button onClick={this.doAction}>Delete</button>
        </td></tr>
      </tbody>
      </table>
    </div>)
  }
}

export default Firedelete;
```

以上。

<br>
[React.js & Next.js超入門のチャプター６を改変：Firestore使用するようにした③](https://qiita.com/atomyah/items/f9a632ca1302d936324c)
につづく