Series: react-firestore

React で Firestore のデータを読み取って表示する

自分が作りたいものを実現するためにどうしてもクライアントサイドで Firestore のデータを読み込む必要にかられたので React でデータ読み込みを実装する。

開発環境

  • node v16.6.0
  • npm v7.19.1
  • react v17.0.2

本文

Firestore のデータの中身は 前々回 のデータを利用する。

React で新規プロジェクト作成

React 初心者なので チュートリアル の真似をして create-react-app で新規プロジェクトを作成する。

npx create-react-app reactblog

作成が終わったら src/App.js からいらない部分を消して下記のようにする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import React from 'react';
import './App.css';

function App() {
  return (
    <div>
      <main>
        テスト
      </main>
    </div>
  );
}

export default App;

src/App.css の中身は空にしておく。

これで npm start でサーバー起動すれば、「テスト」とだけ書かれた画面が出るはず。

Firebase 追加

次に Firebase を追加する。

Firebase を JavaScript プロジェクトに追加する に従っていき、src/App.js を下記のようにする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import React from 'react';
import './App.css';
import firebase from "firebase/app";

const firebaseConfig = {
  // 自分のプロジェクトの内容に差し替える
};

firebase.initializeApp(firebaseConfig);

function App() {
  return (
    <div>
      <main>
        テスト
      </main>
    </div>
  );
}

export default App;

ここまでではまだ画面には「テスト」と書いてあるだけのはず。

Firestore からデータを読み込む

Cloud Firestore を使ってみる に従い、firestore を追加する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React from 'react';
import './App.css';
import firebase from "firebase/app";
import "firebase/firestore";

const firebaseConfig = {
  // 自分のプロジェクトの内容に差し替える
};

firebase.initializeApp(firebaseConfig);

const db = firebase.firestore();

db.collection("posts").get().then((querySnapshot) => {
  querySnapshot.forEach((doc) => {
      console.log(doc.id, '=>', doc.data());
  });
});

function App() {
  return (
    <div>
      <main>
        テスト
      </main>
    </div>
  );
}

export default App;

これで画面は「テスト」と書いてあるままだが、ブラウザのコンソールにデータが表示されるはず。

画面にデータを表示する

timestamp の表示が面倒なので、一旦 timestamp 以外を表示する。

名前はなんでもいいがクラスを作り、データ読み込みを componentDidMount 内で行って state に値を入れてみる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import React from 'react';
import './App.css';
import firebase from "firebase/app";
import "firebase/firestore";

const firebaseConfig = {
  // 自分のプロジェクトの内容に差し替える
};

firebase.initializeApp(firebaseConfig);

const db = firebase.firestore();

class Blog extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      items: []
    };
  }

  componentDidMount() {
    const items = [];

    db.collection("posts").get().then((querySnapshot) => {
      querySnapshot.forEach((doc) => {
        let item = doc.data();
        item.id = doc.id;
        items.push(item);
      });
      this.setState({ items: items });
    });
  }

  render() {
    const items = this.state.items;

    return (
      <ol>
        {items.map((item) => {
          return (
            <li key={item.id}>
              <div>{item.id}</div>
              <div className="App-text">{item.text}</div>
            </li>
          );
        })}
      </ol>
    );
  }
}

function App() {
  return (
    <div>
      <main>
        <Blog />
      </main>
    </div>
  );
}

export default App;

また src/App.css に改行を有効にするスタイルを作っておく。

.App-text {
  white-space: pre-line;
}

これで画面上にデータが表示されるようになって、改行も反映されているはず。

timestamp を表示する

timestamp 型の中身はそのまま表示しようとしてもエラーになったので、Day.js で変換して表示した。

npm install dayjs --save

でインストールしてから import 文追加し、変換処理を追加する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import React from 'react';
import './App.css';
import firebase from "firebase/app";
import "firebase/firestore";
import dayjs from 'dayjs';

const firebaseConfig = {
  // 自分のプロジェクトの内容に差し替える
};

firebase.initializeApp(firebaseConfig);

const db = firebase.firestore();

class Blog extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      items: []
    };
  }

  componentDidMount() {
    const items = [];

    db.collection("posts").get().then((querySnapshot) => {
      querySnapshot.forEach((doc) => {
        let item = doc.data();
        item.id = doc.id;
        items.push(item);
      });
      this.setState({ items: items });
    });
  }

  render() {
    const items = this.state.items;

    return (
      <ol>
        {items.map((item) => {
          const created = dayjs(item.created.toDate());
          const updated = dayjs(item.updated.toDate());
          return (
            <li key={item.id}>
              <div>{item.id}</div>
              <div className="App-text">{item.text}</div>
              <div>
                <time dateTime={created.format('YYYY-MM-DDTHH:mm:ss')}>
                  {created.format('YYYY-MM-DD HH:mm:ss')}
                </time>
              </div>
              <div>
                <time dateTime={updated.format('YYYY-MM-DDTHH:mm:ss')}>
                  {updated.format('YYYY-MM-DD HH:mm:ss')}
                </time>
              </div>
            </li>
          );
        })}
      </ol>
    );
  }
}

function App() {
  return (
    <div>
      <main>
        <Blog />
      </main>
    </div>
  );
}

export default App;

これで timestamp 型のデータも表示できた。

今回はここまで。