번개장터를 클론코딩 하는데, 글작성페이지에서 사진을 넣으면 미리보기를 보여주는 부분을 어떻게 해야할지 고민하게 되었다. 구글링해보면 나오긴 하지만 react를 사용하는데 getElementById나 className으로 어떤 값을 변경해주는게 좀.. 말이 안돼서 혼자 어떻게 react 스럽게 해볼지 고민함.
그러다가 커스텀훅으로 usePreview를 만들게되었다.. !! ! !
import { useState } from "react";
export const usePreview = () => {
const [previewUrl, setPreviewUrl] = useState(null);
const preview = (imgFile) => {
if (!imgFile) {
return null;
}
const reader = new FileReader();
reader.onload = () => {
const fileOnload = reader.result;
return setPreviewUrl(fileOnload);
};
reader.readAsDataURL(imgFile);
};
return { preview, previewUrl };
};
참고자료 https://developer.mozilla.org/ko/docs/Web/API/FileReader
어떻게든 만들고나니까 뿌듯은 한데.. reader.onload일때 나오는 값을 어떻게 밖으로 꺼내줄지 엄청나게 고민하다가 useState를 사용했다.
사용법은 다음과 같다.
// 업로드한 이미지 미리보기 커스텀훅
const { preview, previewUrl } = usePreview();
{inputValue.img ? (
<StPhotoPreview url={`${previewUrl}`}>
<button type="button" onClick={deletePhotoHandler}>
삭제
</button>
</StPhotoPreview>
) : null}
styled-component에 props로 url을 보내줘서 div의 background-image를 변경하도록 했다.
export const StPhotoPreview = styled.div`
width: 202px;
height: 202px;
background-repeat: no-repeat;
background-size: cover;
${({ url }) => {
return `background-image:url(${url})`;
}}
`;
근데 여기서, useEffect를 활용하여 이미지파일의 존재 여부가 변할때마다 화면을 리렌더링 해줘야함.(삭제버튼도 만들어서 이미지값이 null이었다가 있었다가 이러기때문...)
따라서
useEffect(() => {
preview(inputValue.img);
}, [inputValue.img]);
이렇게 처리해주면 된다.