먼저 fweet가 변했을 때(onChange) 그걸 읽어올 수 있도록 만들어야함.
그리고 파일을 읽기 원하기 때문에 fileReader API
를 사용
참고문서 : https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
그리고 나온 result값을 state로 저장
<img src={state}/>
로 저장된 state를 사용
Home.js
const [fileAddress, setFileAddress] = useState("");
const onFileChange = (event) => {
const {
target: { files },
} = event;
const theFile = files[0];
// console.log(theFile);
const reader = new FileReader();
//파일로딩이 끝날때 finishedevent를 갖게 됨
reader.onloadend = (finishedEvent) => {
// console.log(finishedEvent); 여기서 result값이 string으로 아주 길게 나옴 이걸 state로 저장할것임
//result를 카피해서 새창에 붙여넣으면 사진이 뜸 -> 이미지경로가되는것
const {
currentTarget: { result },
} = finishedEvent;
//파일
setFileAddress(result);
};
//데이터를 얻음
reader.readAsDataURL(theFile);
};
...
return(
{fileAddress && (
<div className="imgWrap">
<img
src={fileAddress}
width="100px"
height="100px"
alt="img"
/>
<div className="clearButton">
<button onClick={onClearPhotoClick}>Clear</button>
</div>
</div>
)}
</div>
)
Home.js
const onClearPhotoClick = () => {
setFileAddress(null);
};
...
return(
<button onClick={onClearPhotoClick}>Clear</button>
)
import { getStorage } from "firebase/storage";
export const storageService = getStorage();
uploadString
함수 이용참고문서 문자열에서 업로드 부분
Home.js
import { ref, uploadString, getDownloadURL } from "firebase/storage";
const handleSubmit = async (e) => {
e.preventDefault();
const fileRef = ref(storageService, //하위위치 폴더 만들기 모든 유저의 사진은 아이디와 분리되어있음. 그리고 사진에다가 이름을 랜덤으로 만들어 주기`${userObj.uid}/${uuidv4()}`);
const response = await uploadString(fileRef, fileAddress, "data_url");
console.log(respond)
};
getDownloadURL
함수 이용참고문서: https://firebase.google.com/docs/storage/web/download-files?hl=ko
Home.js
import { ref, uploadString, getDownloadURL } from "firebase/storage";
const handleSubmit = async (e) => {
e.preventDefault();
const fileRef = ref(storageService,
const response = await uploadString(fileRef, fileAddress, "data_url");
//콘솔 찍으면 사진의 url을 다운받게 됨.
// console.log(await getDownloadURL(response.ref));
fileUrl = await getDownloadURL(response.ref);
const fweetobject = {
text: content,
userName: userObj.displayName,
createAt: Date.now(),
creatorId: userObj.uid,
fileUrl //object에 fileUrl 추가
};
await addDoc(collection(dbService, "fweets"), fweetobject);
setContent("");
setFileAddress("");
};
fileAddress
이 있는 경우에 img 태그가 보이도록 수정Home.js
const handleSubmit = async (e) => {
e.preventDefault();
let fileUrl = ""; //사진이 없다면 비어있는 string
if (fileAddress !== "") {
const fileRef = ref(storageService, `${userObj.uid}/${uuidv4()}`);
const response = await uploadString(fileRef, fileAddress, "data_url");
fileUrl = await getDownloadURL(response.ref);
}
...
fweet한 내용을 storage에서 삭제해야함.
참고 문서 : https://firebase.google.com/docs/storage/web/delete-files?hl=ko
import { ref, deleteObject } from "firebase/storage";
Fweet.js
const handleDelete = async () => {
const ok = window.confirm("Are you sure?");
if (ok) {
await deleteDoc(FweetTextRef);
await deleteObject(ref(storageService, fweetObj.fileUrl));
}
};
⭐️ 완성화면
❗️어려웠던 점
역시나 ver9으로 하는 것이 쉽지 않았다..
또 이미 firestore로 작성했던 부분을 사진을 추가 저장함으로써
storage함수로 바꾸는 점이 어려웠음..
다른 사람들이 한 것도 참고하고 공식문서 계속보면어 각 메소드가 어떤 역할을 하는지 파악하기 위해 애썼다.
마지막에 사진 첨부 취소하고 같은 사진 재첨부하려니까 안되어서 확인해보니
input에 value가 삭제 안되는 거 같아 첨부취소시 value값 공란으로 두는 것으로 바꿨다. 사진 재첨부 되긴하는데 수정이 좀 필요할 듯 싶다..
➕➕ ❗️오류 수정
이 때 작업할 때는 몰랐는데 정리하고 보니 삭제할 때 에러가 발생했다.
사진이 있는 경우에 삭제할 때는 오류가 안나서 몰랐음. ;;;
그러나 사진이 없는 경우에는 아래와 같은 오류가 발생했다.
Uncaught (in promise) FirebaseError: Firebase Storage: The operation 'deleteObject' cannot be performed on a root reference, create a non-root reference using child, such as .child('file.png'). (storage/invalid-root-operation)
해석이랑 검색해보니까 참조 문제 인거 같아서 myBase.js 거치지 않고
다이렉트로 import하고 다양하게 바꿔봤는데 안됐음.
알고보니까 사진이 없는 경우에 즉 storage에 저장된게 없는 경우에
(단순 글로된 fweet) 삭제할 때 오류가 발생하는 거였음.
생각해보면 당연함...deleteObject는 storage메소드
니까 해당이 안되어서
에러가 생기는 거였음...
결국에는 조건문을 달아서 fweetObj.fileUrl !== ""
일 때 함수 실행하도록 수정함.
이런 조건문 잊지말고 달자구!!😉