イオン、反応、firebaseとtypescriptで完全なリアルタイムの世論調査アプリを構築する(パート2)


イオン、反応とFireBaseパート2でリアルタイムポーリングアプリケーションを構築する


最後の部分(https://gymconsole.app/blog/ionic-firebase-poll-app)では、我々は主に反応とイオンと私たちのアプリのUIを構築しました.我々も、世論調査を嘲笑しました、そして
回答オブジェクト.
この部分では、最終的にFirebaseを追加し、アプリを完全に機能させるつもりです.
アプリケーションの完全なソースコードはここにあります.
https://github.com/RalliPi/realtime-poll-app
そして、ここで我々のアプリのように我々が行われているようです
Poll app demo video

コーディングを始める前に、FireBaseプロジェクトを設定する必要があります。


https://console.firebase.google.comに向かい、新しいプロジェクトを作成します.すべての必須フィールドを埋めて
プロジェクトが作成されました.
次に、'クラウドFirestore 'をクリックし、新しい雲のFirestoreデータベースを作成します.
データベースが作成されると、次のようになります.

我々の最初の世論調査に加わりましょう.この記事では、プログラムによって新しいポーリングを追加する方法を説明しません.投票に入る
手とユーザーによって我々のアプリとの回答のために投票することができます.(実際に我々のアプリからの世論調査を作成する別の記事では
未来)
' Start Collection 'をクリックし、コレクションIDとして' polls 'を入力します.
投票は、ユーザーが投票することができます.をクリックします.
我々の最初の世論調査に加わりましょう.文書idとして' poll 1 'を使用し、型のテキストというフィールドを追加します.

今私たちの世論調査に可能な回答を追加することができます.ここでサブコレクションを使用します.サブコレクションは基本的にA
つのドキュメントの中のコレクション.我々は必要に応じて世論調査に多くの答えを保存するには、この機能を使用します.
サブコレクション内のすべてのドキュメントは親ドキュメントに属します.
新しく作成されたpollドキュメント内の「Start Collection」をクリックします.サブコレクション'回答'を呼び出し、新しい
それの文書.この文書は「量」と呼ばれるフィールドを持っていなければなりません
我々のアプリで表示されるテキストである'テキスト'と呼ばれるフィールドを受信した回答.

さあ、FireBaseアプリの接続設定をコピーしましょう.後で必要です.プロジェクトの設定
左上隅の小さなギアをクリックします.スクロールダウンしてFireBase Webアプリケーションの設定をコピーします.
そのように見えます.
const firebaseConfig = {
  apiKey: "yourapikey",
  authDomain: "yourauthdomain",
  databaseURL: "yourdatabaseurl",
  projectId: "yourprojectid",
  storageBucket: "yourstoragebucket",
  messagingSenderId: "yourmessagingsenderid",
  appId: "yourappid"
};
警告:
このチュートリアルでは、Firestoreデータベースにセキュリティルールの設定がないことを前提としています.つまり、誰もがあなたのデータベースに読み書きできます.これは非常に危険であり、生産に展開する必要はありません.
しかし、このガイドはセキュリティ規則についてではありません.それで、私はここで彼らと議論しません.
OK、それはファイアベース側にあります.コーディングを得るまでの時間です.あなたのエディタでパート1のプロジェクトを開きます.
コードを書く前に、まず依存性をインストールする必要があります.あなたのアプリケーションを変更するあなたの端末を開きます
ディレクトリと次のコマンドを実行します
npm install firebase
これはFirebase SDKをプロジェクトに追加します.Firestoreデータベースと通信するために必要です.
FireStoreデータベースを設定します.srcフォルダで、dbという新しいファイルを作成します.それは私たちを保持します
Firebaseの設定.
次のコードをペーストします
import * as firebase from "firebase/app";
import "firebase/firestore";

var firebaseApp = firebase.initializeApp({
  apiKey: "yourapikey",
  authDomain: "yourauthdomain",
  databaseURL: "yourdatabaseurl",
  projectId: "yourprojectid",
  storageBucket: "yourstoragebucket",
  messagingSenderId: "yourmessagingsenderid",
  appId: "yourappid",
});

export const db = firebaseApp.firestore();
まずFirebaseとFireStoreをインポートします.その後、以前にコピーした設定でfirebaseを初期化します.イン
最後の行はFirestoreオブジェクトをエクスポートしてDBと呼びます.すべてのファイルから簡単にFireStoreにアクセスすることができますこの方法
インポートdb .TS

簡単にアクセスするためのフックを作成する


我々が直接我々のページで使った世論調査と答えオブジェクトを覚えていてください.我々は2つのフックでそれらを交換するつもりです.それら
フックは、投票と世論調査回答をロードして、保存することに責任があります.
ページコンポーネントに移動し、次のコンテンツを入れ替えます.
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonCard,
  IonCardContent,
  IonList,
  IonItem,
  IonLabel,
} from "@ionic/react";
import React, { useState, useEffect } from "react";
import "./Home.css";
import { usePoll, usePollAnswers } from "../hooks/poll";

const Home: React.FC = () => {
  var poll = usePoll("poll1");
  var { answers, vote } = usePollAnswers("poll1");

  const onVote = (
    e: React.MouseEvent<HTMLIonItemElement, MouseEvent>,
    id: string
  ) => {
    e.preventDefault();
    let answer = answers.find((a) => a.id === id);
    vote(answer!.id);
  };

  const answerList = () => {
    return answers.map((answer) => (
      <IonItem onClick={(e) => onVote(e, answer.id)} key={answer.id}>
        <IonLabel>{answer.text}</IonLabel>
        <IonLabel>{answer.amount}</IonLabel>
      </IonItem>
    ));
  };

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Ionic Blanks</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        <IonCard>
          <IonCardContent>
            {poll != null ? poll.text : "loading poll..."}
          </IonCardContent>
        </IonCard>
        <IonList>{answerList()}</IonList>
      </IonContent>
    </IonPage>
  );
};

export default Home;
コンポーネントはほとんど古いバージョンと同じように見えます.我々は、2つのカスタムメイドのフックで
Usepollとusepoll答え.我々は使用したい世論調査のIDを通過し、フックは残りを処理します.
UsePollはFirestoreデータベースからpollオブジェクトを返すだけで、その結果を返す
投票に参加し、さらに投票方法として投票に使用することができます投票の答えを投票します.
作業を始め、フックを実行しましょう.
あなたのsrcディレクトリに新しいディレクトリを作成します.POLというTSファイルです.それのTS.
次のコンテンツを入力します.
import { useState, useEffect } from "react";
import { db } from "../db";
import { Poll } from "../model/poll";
import { PollAnswer } from "../model/pollAnswer";
import { firestore } from "firebase";

export const usePoll = (pollId: string) => {
  const [poll, setPoll] = useState<Poll | null>(null);

  useEffect(() => {
    //load current poll
    db.collection("polls")
      .doc(pollId)
      .get()
      .then((poll: firestore.DocumentSnapshot<firestore.DocumentData>) => {
        if (poll.exists) {
          setPoll({
            id: poll.id,
            text: poll.data()!.text,
          });
        } else {
          console.log("couldn't find poll");
        }
      })
      .catch((error) => {
        console.log("error loading poll: " + error);
      });
  }, []);

  return poll;
};

export const usePollAnswers = (pollId: string) => {
  const [answers, setAnswers] = useState<PollAnswer[]>([]);

  //setup data listeners
  useEffect(() => {
    //load all possible answers
    var removeAnswersSnapshot = db
      .collection("polls")
      .doc(pollId)
      .collection("answers")
      .onSnapshot((snapshot) => {
        var answerObjects: PollAnswer[] = [];
        snapshot.docs.forEach((doc) => {
          answerObjects.push({
            id: doc.id,
            text: doc.data().text,
            amount: doc.data().amount,
          });
          setAnswers(answerObjects);
        });
      });
    return () => {
      removeAnswersSnapshot();
    };
  }, []);

  const vote = (id: string) => {
    var newAnswers = [...answers];
    var answer = newAnswers.find((a) => a.id === id);

    db.collection("polls")
      .doc(pollId)
      .collection("answers")
      .doc(answer!.id)
      .set(
        {
          amount: answer!.amount + 1,
        },
        { merge: true }
      );
  };

  return { answers, vote };
};
あなたが見ることができるように、我々は2つの機能/フックを輸出しています.
usepollフックがどのように機能するかを見てみましょう.
ここでUSENTフックの助けを借りて、タイプpollのローカル州オブジェクトを宣言します.それは基本的に我々
以前は直接私たちのページコンポーネントにしました.
実際のDatabaseCallを使用しています.useeffect hookは常に値のいずれかのときに実行される
2番目のパラメータの変更.2番目のパラメータとして空のリストを渡すと、フックは
コンポーネントがマウントされます.
それで、ユーザーがホームページを打つ直後に、我々は世論調査をロードしています.
db.collection("polls").doc(pollId).get();
これは、FireBase DocumentSnapshotを含むプロミスを返します.このスナップショットの格納されたデータは同じです
我々の世論調査タイプとして.しかし、我々はちょうどそれを投げることができません.我々は、新しいプロパティを構築する必要があります
DocumentSnapshot :
setPoll({
  id: poll.id,
  text: poll.data()!.text,
});
それで、我々のローカル州オブジェクト世論調査は我々がちょうどサーバーからロードされるデータを保持します.
我々のフックからローカル世論調査オブジェクトを返すことによって、我々は機能の外側からこの部分へのアクセスを得ることができます.
涼しい部分は、フックの内部状態が変化するとき(データがロードされたとき)、返されたオブジェクト
また、'変更'(変更されませんが、それは新たに設定されたデータを保持).
ページコンポーネントから実際のデータベース読み込みロジックを抽象化しました.我々は今、どこからでも投票をロードすることができます
ちょうど呼び出しで我々のアプリケーション
var myNewPoll = usePoll("myPollId");
usepollanswer関数に入りましょう.それは少し複雑ですが、どのようにusepoll関数を理解した場合
WorldPollAnswersフックの問題はありません.
我々は再びローカル州を使用しています.しかし、今回は単一の投票の代わりにpollanswerのリストを保存する必要があります.我々は
再び有効なフックでDBを呼ぶこと.
今回は、一度だけ値を得るだけではなく、リアルタイムリスナーを設定しています.
var removeAnswersSnapshot = db
  .collection("polls")
  .doc(pollId)
  .collection("answers")
  .onSnapshot(callback);
これは、我々のdbの世論調査文書のサブコレクションのリスナーを設定します.サブコレクションは基本的に別です
データベース内の1つのドキュメントだけに存在するコレクションです.データベース内のすべての単一の世論調査は
この特定の世論調査に属している答えの自身のコレクション.コールバックメソッドは
私たちのvalueset変化の文書(世論調査のどんな応答オブジェクトも変更されます).
.onSnapshot(snapshot => {
  var answerObjects: PollAnswer[] = [];
  snapshot.docs.forEach(doc => {
    answerObjects.push({
      id: doc.id,
      text: doc.data().text,
      amount: doc.data().amount,
    });
    setAnswers(answerObjects);
  });
})
コールバックでは、すべてのドキュメントをループして、新しいランナーの配列を構築します.最後に、私たちは
新しく作成された配列は、ローカルの状態オブジェクトです.
今回は、useEffectsで実行している関数は関数を返します.これは有効な機能です.すべてのコード
この関数は、コンポーネントのアンマウント時に呼び出されます.電話している
removeAnswersSnapshot();
がある.これはFirestoreによって提供されるOnSnapshotメソッドによって返されるメソッドです.このメソッドを呼び出す
リスナーをDBから削除します.それで、我々はもはやページのすぐにデータベース変化について最新版を得ていません
コンポーネントアンマウント.
我々のために我々の世論調査アプリ機能をするために必要な最後のことは投票機能です.
const vote = (id: string) => {
  var newAnswers = [...answers];
  var answer = newAnswers.find((a) => a.id === id);

  db.collection("polls")
    .doc(pollId)
    .collection("answers")
    .doc(answer!.id)
    .set(
      {
        amount: answer!.amount + 1,
      },
      { merge: true }
    );
};
投票メソッドは、その唯一のパラメータとしてpoll答えのIDをとります.その後、ローカル州での答えを探す
idを比較することによってオブジェクトを設定します.次に、setメソッドを呼び出して、Firestoreデータベースへの書き込みを行います.我々はちょうど
オブジェクトの量フィールドを更新します.渡されたマージパラメータはFirestoreに古いオブジェクトをマージするよう指示します
それは現在私たちが提供する新しい値を格納しています.それはすべてデータベースに書き込む必要があります.
クールな部分は、我々が世論調査の量フィールドを増やすときです.私たちのスナップショットのリスナーのリスナー
すぐにトリガし、それに応じて我々のUIを更新します.ここではどんな仕事もする必要はありません.
この変更を行います.プロジェクトパスをターミナルとタイプで開きます
npm run start
これは開発サーバーを起動します、そして、あなたは世論調査アプリをテストすることができなければなりません.いくつかのブラウザのWindows
それはリアルタイムで同期し、その状態を保存してください.
それです.我々は、イオンの反応の助けを借りて、コードのいくつかの行を完全にリアルタイムのリアルタイムアプリを構築した
ファイアストア.
あなたが内容のこのタイプを楽しむならば、より多くのチュートリアルを得るか、さえずりの上で私とつながってください
.
あなたと話をしたり、プロジェクトを手伝ったりしてうれしいです