【Firebase】閲覧機能を実装する

firebase.js

import { initializeApp } from "firebase/app";
import { getStorage } from "firebase/storage";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
};

const app = initializeApp(firebaseConfig);
export const storage = getStorage(app);
export const db = getFirestore();

App.jsx

import React from 'react';
import Upload from './Upload';

const App = () => {
  return (
    <React.Fragment>
      <Upload />
    </React.Fragment>
  );
}

export default App;

userConst.js

import { serverTimestamp } from 'firebase/firestore';

const user = Object.freeze({
  id: '',
  urlList: [],
  createdAt: serverTimestamp()
});

export { user };

Image.jsx

import React from 'react';

const Image = (props) => {
  return (
    <React.Fragment>
      <img src={props.url} alt={props.name} />
    </React.Fragment>
  );
}

export default Image;

Upload.jsx

import React, { useState, useEffect } from 'react';
import { ref, uploadBytes, getDownloadURL } from 'firebase/storage';
import { collection, addDoc, getDocs, updateDoc, query, orderBy } from 'firebase/firestore';
import { storage, db } from '../scripts/firebase';
import { user } from '../scripts/userConst';
import Image from './Image';

const maxImageCount = 5;

const getDataURL = (file) => {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = () => {
      const dataURL = reader.result;
      resolve(dataURL);
    }
    reader.readAsDataURL(file);
  });
}

const Upload = () => {
  const [files, setFiles] = useState([]);
  const [images, setImages] = useState([]);
  const [posted, setPosted] = useState([]);

  const handleInputChange = async (event) => {
    const fileList = Array.from(event.target.files);
    const imageList = [];
    for (const file of fileList) {
      const dataURL = await getDataURL(file);
      imageList.push(
        <Image key={file.name} url={dataURL} name={file.name} />
      );
    }
    setFiles(fileList);
    setImages(imageList);
  }

  const handleSubmit = async (event) => {
    event.preventDefault();
    const usersRef = collection(db, 'users');
    const userDocRef = await addDoc(usersRef, user);
    const urlList = await Promise.all(files.map(async (file) => {
      const storageRef = ref(storage, `images/${userDocRef.id}/${file.name}`);
      await uploadBytes(storageRef, file).then(() => {
        console.log('Uploaded!');
      });
      const url = await getDownloadURL(storageRef);
      return url;
    }));
    await updateDoc(userDocRef, {id: userDocRef.id, urlList});
  }

  const getPostedImages = async () => {
    const usersRef = collection(db, 'users');
    const q = query(usersRef, orderBy('createdAt', 'desc'));
    const querySnap = await getDocs(q);
    const postedList = [];
    let count = 0;
    for (const doc of querySnap.docs) {
      const urlList = doc.data().urlList;
      for (const url of urlList) {
        const name = url.split('?')[0].split('%2F').slice(-1)[0];
        postedList.push(
          <Image key={url} url={url} name={name} />
        );
        count++;
        if (count >= maxImageCount) {
          setPosted(postedList);
          return;
        }
      }
    }
    setPosted(postedList);
  }

  useEffect(() => {
    getPostedImages();
  }, []);

  return (
    <React.Fragment>
      <form>
        <input
          type='file'
          accept='image/*'
          multiple
          onChange={handleInputChange}
        />
        <button type='submit' onClick={handleSubmit}>送信</button>
      </form>
      { images }
      <p>----------------------------------------------------------------------------------------------------</p>
      { posted }
    </React.Fragment>
  );
}

export default Upload;

参考

Cloud Firestore にデータを追加する  |  Firebase Documentation

コメント

タイトルとURLをコピーしました