web-dev-qa-db-ja.com

React-firestore-hooksはクラウドのファイアストアからデータベースレコードを取得します

データベースへの呼び出しを簡略化できるように、reactアプリで react-firebase-hooks を使用する方法を理解しようとしています。

この試みの以前のバージョン( この質問 のヘルプで解決)は、このクラスコンポーネントをcomponentDidMount関数で使用しました(機能しました):

class Form extends React.Component {
    state = {
      options: [],
    }

    async componentDidMount() {
        // const fsDB = firebase.firestore(); // Don't worry about this line if it comes from your config.
        let options = [];
        await fsDB.collection("abs_for_codes").get().then(function (querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, ' => ', doc.data());
            options.Push({
                value: doc.data().title.replace(/( )/g, ''),
                label: doc.data().title + ' - ABS ' + doc.id
            });
            });
        });
        this.setState({
            options
        });
    }

フックを使用して、react-firebase-hooksを使用してデータベースからデータを取得する方法を学習しようとしています。私の現在の試みは:

import { useDocumentOnce } from 'react-firebase-hooks/firestore';

また、「react-firebase-hooks/firestore」から{useDocument}をインポートしてみました。

const [snapshot, loading, error] = useDocumentOnce(
  firebase.firestore().collection('abs_for_codes'),
  options.Push({
    value: doc.data().title.replace(/( )/g, ''),
    label: doc.data().title + ' - ABS ' + doc.id
  }),
);

これにより、「useDocumentOnce」が定義されていないというエラーが生成されます。

私は試しました(それも間違っています):

const [snapshot, loading, error] = useDocumentOnce(
  firebase.firestore().collection('abs_for_codes'),
  {snapshot.Push({
    value: doc.data().title.replace(/( )/g, ''),
    label: doc.data().title + ' - ABS ' + doc.id,
  })},
);

Firebaseからコレクションを取得するにはどうすればよいですか?私は、abs_for_codesと呼ばれるFirebaseのコレクションから読み取ったオプションを選択メニューに入力しようとしています。

UseStateのポイントは、もう状態を宣言する必要がないことだと思います。以下の選択試行を追加したことを呼び出すだけです。

<Select 
            className="reactSelect"
            name="field"
            placeholder="Select at least one"
            value={valuesSnapshot.selectedOption}
            options={snapshot}
            onChange={handleMultiChangeSnapshot}
            isMulti
            ref={register}
          />

参考までに、フォームには他に2つの選択メニューがあります。それらのオプションを設定するために使用するconstは手動で定義されますが、それらの値を確立するプロセスは以下のとおりです。

const GeneralTest = props => {
  const { register, handleSubmit, setValue, errors, reset } = useForm();
  const { action } = useStateMachine(updateAction);
  const onSubit = data => {
    action(data);
    props.history.Push("./ProposalMethod");
  };

  const [valuesStudyType, setStudyType] = useState({
    selectedOptionStudyType: []
  });

  const [valuesFundingBody, setFundingBody] = useState({
    selectedOptionFundingBody: []
  });


  const handleMultiChangeStudyType = selectedOption => {
    setValue("studyType", selectedOption);
    setStudyType({ selectedOption });
  };

  const handleMultiChangeFundingBody = selectedOption => {
    setValue("fundingBody", selectedOption);
    setFundingBody({ selectedOption });
  };

  useEffect(() => {
    register({ name: "studyType" });
    register({name: "fundingBody"});
  }, []);

データベースクエリからスナップショットを追加するにはどうすればよいですか?

次のように、スナップショットに対して同様のhandleMultiChange constおよびuseEffectレジスタステートメントを作成してみました。

  const [snapshot, loading, error] = useDocumentOnce(
    firebase.firestore().collection('abs_for_codes'),
    snapshot.Push({
      value: snapshot.data().title.replace(/( )/g, ''),
      label: snapshot.data().title + ' - ABS ' + snapshot.id
    }),
  );

  const [valuesField, setField ] = useState({
    selectedOptionField: []
  });

  const handleMultiChangeField = selectedOption => {
    setValue("field", selectedOption);
    setField({ selectedOption });
  };

しかし、それは機能しません。エラーメッセージは言う:

ReferenceError:初期化前に「スナップショット」にアクセスできません

選択メニューにデータベースのデータを入力する方法の例が見つかりません。

次の試み

useEffect(
    () => {
      const unsubscribe = firebase
        .firestore()
        .collection('abs_for_codes')
        .onSnapshot(
          snapshot => {
            const fields = []
            snapshot.forEach(doc => {
              fields.Push({
                value: fields.data().title.replace(/( )/g, ''),
                label: fields.data().title + ' - ABS ' + fields.id
              })
            })
            setLoading(false)
            setFields(fields)
          },
          err => {
            setError(err)
          }
        )
      return () => unsubscribe()
    })

これも機能しません-次のようなエラーメッセージが表示されます。

TypeError:fields.dataは関数ではありません

次の試み

ドキュメントの呼び出しではなくコレクションを検索する必要があることを認識しながら、useCollectionDataがuseCollectionOnceよりも適切であるかどうかがわかりません(useCollectionDataが提供するものに関するドキュメントを理解できません)。

const [value, loading, error] = useCollectionOnce(
  firebase.firestore().collection('abs_for_codes'),
  {getOptions({
    firebase.firestore.getOptions:
    value: doc.data().title.replace(/( )/g, ''),
    label: doc.data().title + ' - ABS ' + doc.id,
  })},
);

これも誤りです。エラーメッセージはgetOptions行を指しており、次のように述べています。解析エラー:予期しないトークン、予期される "、"

私のコレクションには、いくつかのドキュメントがあります。それぞれに、数値とテキスト文字列の2つの属性があります。私のオプションは、数値とテキスト文字列を一緒に表示するだけでなく、テキストとして挿入した頭字語をフォーマットすることです(componentDidMountを使用して行うことができました)。

次の試み

次にこれを試しました:

const fields = firebase.firestore.collection("abs_for_codes").get().then(function(querySnapshot) {
  querySnapshot.forEach(function(doc) {
    console.log(doc.id, ' => ', doc.data());
    fields.Push({
        value: doc.data().title.replace(/( )/g, ''),
        label: doc.data().title + ' - ABS ' + doc.id
    });
    });
});

エラーメッセージは言う:TypeError:_firebase__WEBPACK_IMPORTED_MODULE_5 __。firebase.firestore.collection is not a function

次のATTEPMT

const searchFieldOfResearchesOptions = (searchKey, resolver) => {
    // for more info
    // https://stackoverflow.com/questions/38618953/how-to-do-a-simple-search-in-string-in-firebase-database
    // https://firebase.google.com/docs/database/rest/retrieve-data#range-queries
    fsDB
      .collection("abs_for_codes")
      .orderBy("title")
      // search by key
      .startAt(searchKey)
      .endAt(searchKey + "\uf8ff")
      .onSnapshot(({ docs }) => {
        // map data to react-select
        resolver(
          docs.map(doc => {
            const { title } = doc.data();

            return {
              // value: doc.id,
              // label: title
              value: title.data().title.replace(/( )/g, ''),
              label: title.data().title + ' - ABS ' + title.id
            };
          })
        );
      }, setFieldOfResearchesError);
  };

この試みは実際にデータベースからデータを取得するために機能します(うーん)-レンダリングしたいテキストラベルを取得できない場合を除きます。コレクション内の各ドキュメントには2つのフィールドがあります。最初はタイトルで、2番目はID番号です。最後のステップは、テキスト(つまりABS-)を挿入したラベルを作成し、次にID番号とタイトルを一緒に作成することです。

各ドキュメントのタイトルを抽出するために何が機能するかを示すためにコメント付きのコードを追加しましたが、ラベルを希望どおりに作成しようとしても、エラーが発生せず、機能しません。リスト内のドキュメントのタイトル。

誰かが、フックを使用してクラウドのファイヤーストアコレクションからオプションの選択メニューセットを生成する方法を知っていますか?

4
Mel

ここには複数の質問があります。これが役立つかどうかを確認します。

これにより、「useDocumentOnce」が定義されていないというエラーが生成されます。

import { useDocumentOnce } from 'react-firebase-hooks/firestore';

DOCの指示どおりにインポートしていて、このエラーが発生している場合、開発環境に問題があると思います。別のコードエディター、または別のPCを使用してみてください。 あなたが言ったようにそれを正しくインポートしていれば、コードに問題はなく、このエラーは発生しません。これはコードのバグではありません。


useCollectionおよびuseDocumentOnceのドキュメントを参照してください(これらは非常によく似ています)。

enter image description here

enter image description here

そして今あなたがやっていることを見てください:

const [snapshot, loading, error] = useDocumentOnce(
  firebase.firestore().collection('abs_for_codes'),
  {snapshot.Push({
    value: doc.data().title.replace(/( )/g, ''),
    label: doc.data().title + ' - ABS ' + doc.id,
  })},
);

useDocumentOnce関数の正しいパラメーターを送信していません。 document参照とオプションオブジェクトが必要です。 collection参照とその他のコードの束をoptionsパラメータに送信しています。

コードは次のようになります。

const [snapshot, loading, error] = useDocumentOnce(
  firebase.firestore().collection('abs_for_codes').doc('someDocID')
);

OR

const [snapshot, loading, error] = useDocumentOnce(
  firebase.firestore().collection('abs_for_codes').where('someProperty','==','someValue')
);

オプションであるため、optionsパラメーターを含めていないことに注意してください。特定のオプションが必要な場合は送信してください。


useDocumentOnceフックを使用したコンポーネントの外観。

import { useDocumentOnce } from 'react-firebase-hooks/firestore';

const FirestoreDocument = () => {
  const [snapshot, loading, error] = useDocumentOnce(
    firebase.firestore().collection('someCollection').doc('someDocID'),
    {
      snapshotListenOptions: { includeMetadataChanges: true },
    }
  );
  return (
    <div>
      <p>
        {error && <strong>Error: {JSON.stringify(error)}</strong>}
        {loading && <span>Document: Loading...</span>}
        {snapshot && (
          <span>
            Document: {JSON.stringify(snapshot.data()}
          </span>
        )}
      </p>
    </div>
  );
};
0
cbdeveloper