Skip to content

Conversation

@KimKyuHoi
Copy link
Collaborator

@KimKyuHoi KimKyuHoi commented Feb 4, 2025

Pull request

Related issue

Motivation and context

Solution

  • use-file-managements.tsx
import type { FileData } from './file-data.type';
import { validateFileSize, generateVideoThumbnail } from '../lib/file.utils';
import { useState, useEffect } from 'react';

/**
 * 파일 관리를 위한 커스텀 훅
 * @returns {Object} 파일 관리 관련 메서드와 상태
 * - selectedFiles: 선택된 파일 목록
 * - handleFileChange: 파일 선택 이벤트 핸들러
 * - handleRemoveFile: 파일 제거 메서드
 * - setSelectedFiles: 파일 목록 설정 함수
 */
export const useFileManagements = () => {
  const [selectedFiles, setSelectedFiles] = useState<FileData[]>([]);

  const processFile = async (file: File): Promise<FileData | null> => {
    if (!validateFileSize(file)) return null;

    const fileData: FileData = {
      id: Math.random().toString(36).substring(7),
      name: file.name,
      file,
      preview: URL.createObjectURL(file),
      type: file.type.startsWith('image/') ? 'image' : 'video',
    };

    if (fileData.type === 'video') {
      try {
        fileData.thumbnailUrl = await generateVideoThumbnail(file);
      } catch (error) {
        console.error('Failed to generate thumbnail:', error);
      }
    }

    return fileData;
  };

  /**
   * 파일 선택 이벤트 핸들러
   * @param event - 파일 input 이벤트
   */
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const handleFileChange = async (
    event: React.ChangeEvent<HTMLInputElement>,
  ) => {
    setIsLoading(true);
    setError(null);

    try {
      const files = Array.from(event.target.files || []);
      event.target.value = '';

      const processedFiles = await Promise.all(files.map(processFile));

      setSelectedFiles((prev) => [...prev, ...processedFiles.filter(Boolean)]);
    } catch (error) {
      setError(error as Error);
    } finally {
      setIsLoading(false);
    }
  };


  useEffect(() => {
    const currentFiles = selectedFiles;

    return () => {
      currentFiles.forEach((file) => {
        URL.revokeObjectURL(file.preview);
      });
    };
  }, [selectedFiles]);

  /**
   * 파일 제거 메서드
   * @param id - 제거할 파일의 ID
   */
  const handleRemoveFile = (id: string) => {
    setSelectedFiles((prev) => {
      const fileToRemove = prev.find((file) => file.id === id);
      if (fileToRemove) {
        URL.revokeObjectURL(fileToRemove.preview);
      }
      return prev.filter((file) => file.id !== id);
    });
  };

  return {
    handleFileChange,
    handleRemoveFile,
    selectedFiles,
    setSelectedFiles,
    isLoading,
    error,
  };
};

코드내에서 useEffect함수와 removeFile 함수 둘이 이중으로 clean up이 문제의 원인이였습니다.

  • removeFile함수가 실행된 후
    • URL.revokeObjectURL(fileToRemove.preview)를 통해 cleanup 됨.
     useEffect(() => {
       const currentFiles = selectedFiles;
    
       return () => {
         currentFiles.forEach((file) => {
           URL.revokeObjectURL(file.preview);
         });
       };
     }, [selectedFiles]);
    • useEffect를 통해 한번 더 cleanup을 통해 남은 배열 자체를 없애버립니다.

How has this been tested

2025-02-04.11.15.45.mov

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the docs/CONTRIBUTING.md document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@KimKyuHoi KimKyuHoi added 🐛 BugFix 버그 수정 🚑 !HOTFIX 급하게 치명적인 버그를 고쳐야하는 경우 🖥️ FE 프론트엔드 무조건 스프린트내에 해야하는 것들 labels Feb 4, 2025
@KimKyuHoi KimKyuHoi added this to the 주톡피아 마일스톤2 milestone Feb 4, 2025
@KimKyuHoi KimKyuHoi requested a review from handje February 4, 2025 02:16
@KimKyuHoi KimKyuHoi self-assigned this Feb 4, 2025
Copy link
Collaborator

@handje handje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

잘 동작합니다!

@KimKyuHoi KimKyuHoi merged commit a1b5587 into dev Feb 4, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

무조건 스프린트내에 해야하는 것들 🐛 BugFix 버그 수정 🖥️ FE 프론트엔드 🚑 !HOTFIX 급하게 치명적인 버그를 고쳐야하는 경우

Projects

None yet

Development

Successfully merging this pull request may close these issues.

파일을 고르고 삭제 뒤 다음 이미지를 클릭했을때 모달창내에서 파일이 안보이는 현상

3 participants