🐥

React.オブジェクト指向: ファイルをアップロードするサンプルコード

2024/05/26に公開

最終形態

page.js
  onClick={async ()=> {
    const file = await new InputFile().get();
    user.thumbnails.push(file);
  }}
Element.Input.js
export class Input {
  constructor(attr) {
    this.El = document.createElement('input');
  }
}

export class InputFile extends Input {
  constructor() {
    super();
    this.El.type = 'file';
    // this.El.setAttribute('multiple', true);
    this.El.setAttribute('accept', 'image/*');
  }
  // TODO: NativeFilePickerを起動する部分とinputからFileを取得する部分を分けたほうがよい
  get() {
    return new Promise((resolve) => {
      this.El.click();
      this.El.addEventListener('change', (event) => {
        console.log(event.target.files);
        const file = event.target.files[0];
        this.validate(file, resolve);
      });
    });
  }
Thumbnails.js
class Thumbnails extends Collection {
  getAlias() {
    return ['users', this.user.uid, 'thumbnails'];
  }
  // @param file: fileObject
  push(file) {
    Storage(this.getAlias()).upload(file).then((snapshot) => {
      super.push({ url: snapshot.url });
    });
  }

いろいろ思考錯誤して破棄したコード:

  onClick={() => {
    // user.uploadThumbnail(file);
    // user.upload(file).toFirestore('thumbnails')
    // user.uploadMediaTo('thumbnails', fileInputRef)
    // fileInputRef.upload('thumbnails')
  }}
  ...
  <input type="file" onChange={handleImage} ref={fileInputRef} hidden />

class User {
  ...
  // @param path: string
  // user.{プロパティ名} === Storage path.
  uploadMediaTo(path, inputElement) {
    const fileData = new FileSelector(inputElement).get();
    Storage(path).push(fileData).then((url) => {
      this[path].push({ url });
    });
  }
  uploadThumbnail() {
    // TODO: `import Ftorage from @/src/services/firebase/apis/storage.js` をインポートして使う
    // Ftorage.xxxx
    // 使い手がわ: onClick={() => {...}} 内とかで
    // ```
    // user.uploadThumbnail().then(() => {
    //   // 成功した場合のsnackBarをだす
    // })
    // .error(() => {
    //   // 失敗した場合のsnackBarをだす
    // })
    // ```
  }

Discussion