[보배빌림] react-hook-form 파일업로드

hyo·2022년 11월 29일
0
post-thumbnail

파일업로드

회원가입 페이지에서 아직 하지못한 이미지파일업로드가 남아있어서 오늘은 이미지파일 업로드, 서버로 URL형식으로 보내기 , 다시 서버로 요청해서 보냈던 URL 받아서 이미지 보여주기! 를 해보았다.

하루종일 걸리긴했지만 나름 성공적으로 된것 같다.

우선 나는 회원가입페이지 form을 react-hook-form을 사용하여 만들던 중이었기에 react-hook-form으로 파일 업로드까지 진행해보았다.

원하던 과정과결과

1.회원가입 페이지에서 파일업로드를 클릭하여 파일을 입력시킨다.
2.입력시킨 파일이미지를 미리보기로 띄워준다.
(참고로 양식중에 주소찾기 버튼을 누르면 페이지가 이동하며 주소찾기 api를 사용할 수 있게 flow를 만들어 뒀다.)
3.아래 email,password 등 양식을 채워넣고 주소찾기를 눌러 주소찾기페이지로 이동한뒤, 주소를 선택하고 다시 회원가입페이지로 페이지전환이 되었을때에도
이전에 넣어뒀던 input value (email,password)가 남아있고 입력시킨 파일이미지도 남아있도록.
4. 회원가입버튼을 누르면 서버로 입력시킨 모든 데이터를 보내 서버에 저장.
5.로그인 후 마이페이지에 입력시켰던 파일이미지도 나오도록.

위와 같은 결과를 원했고
조금전에 90프로 완성하였다.(10% 미달은 밑으로가서 말하도록하겠음.)

우선 react-hook-form을 사용했기에

            <input
              type='file'
              name='photoURL'
              accept='image/*' // image/.png ,image/.jp등등 허용되는 값
              placeholder='이미지'
              {...register('photoURL')}
            />
 

name을 입력한다.
name을 써두면 useForm()에서 watch(),getValues() 매서드를 통해 input값을 불러올 수 있다.

watch('photoURL') , getValues('photoURL') 

입력을 넣을 수도 있는데 그때 setValue() 매서드 사용

setValue('email', 'hyo@naver.com') -> console.log(watch('email')) -> 'hyo@naver.com'

파일업로드 태그가 브라우저에 뜬다.

미리보기처럼 보여주기 위해 useState()를 사용하여 상태를 선언해둔다.

const [preview, setPreview] = useState(''); // url형식으로 상태를 저장할 것이다.

업로드할 파일을 url형식으로 변환시켜주고 그 url을 서버로 post 요청을 보내 회원가입을 할 것이다.

Url 형식으로 바꿔주는 방법은 여러가지가 있지만 나는 URL.createObject() 매서드를 사용할 것이다.

우선 업로드한 이미지를 조회하여 가져와 변수에 할당.

const avatar = watch('photoURL')

그리고 photoURL이 변할때마다 실행시켜줄 함수 구현! -> useEffect()

useEffect(() => {
  if(avatar && avatar.length > 0){ // 업로드한 파일이 존재하고 길이가 있을때
    const file = avatar[0]; // [0]을 한 이유는 콘솔에 찍어보면 0이라는 키값에 File이 들어있다.
    setPreview(URL.createObject(file)); // 아까 만들어둔 미리보기 상태변경함수에 url로 변환시킨 url을 넣어준다.
  
  }
}, [avatar]) // 이러면 avatar가 바뀔때마다 이 함수가 실행된다. 

위 코드로 짜면 파일이 업로드되었을때만 즉, photoURL이 존재할때만 실행된다.
물론 [avatar] 가 변할때 실행을 시작하긴한다.
avatar가 변할때마다 실행시키게 함으로써 주소찾기로 페이지이동(랜더링)되었을때 전역상태에있던 값들이 다시 불려와졌을때도 주소찾기 페이지로 가기전에 photoURL이 있었다면 photoURL도 다시 불려와지므로 useEffect함수가 실행될것이다.

위처럼 내가 만든 회원가입페이지는 주소찾기 버튼을 누르면 페이지가 이동된다.
그러므로 로컬 상태들은 다 초기화가 될것이므로 전역상태로 모든값들을 임시로 저장해둬야한다.
recoil을 사용하여 useRecoilState() 를 써보았다.

const [inputState, setInputState] = useRecoilState(userInfoState) // recoil 파일에 따로 만든 userInfoState -> default : {email: '', password: '' ...}

주소찾기 버튼을 누를때 발생할 이벤트로
현재 input에 입력된 모든 데이터들을 전역상태로 저장!
-> navigate('/주소찾기페이지') -> 주소찾기 선택 마침 -> 전역상태로 저장했던 input 값들을 불러와 input value 값에 넣어주기!

//주소찾기 버튼 눌렀을때 발생하는 이벤트
setInputState(watch());
navigate('/주소찾기페이지')

주소찾기를 마치고 와서 전역상태에 저장했던 데이터들이 입력되고 이미지도 잘 들어온다.
이제 axios를 사용해서 post 요청을 보낼건데 요청할때
data.photoURL = URL.createObject(file).slice(5);
처리를 하고 post요청에 같이 보내준다.
이유는 URL 형식으로 변환해서 나온값은
blob:https://dadadadsadadsa..... 으로 나오기때문에 서버에 url만 보내야한다면 앞에 'blob:'은 뺴고보낸다.

회원가입도 잘되었고 로그인도 잘되었다면

마이페이지로 가서 입력된 이미지를 보기위해

<img src={`blob:${url}`}/> // blob: 을 써줘야 이미지가 보였다. 이거때매 한참 구글링하였다.. 

아참 그리고 회원가입페이지에서 파일업로드하고 URL로 변환시킨상태에서 주소찾기 버튼을 눌렀을때 였나? recoil, URL , freeze 오류가 떳었는데
구글링 해보니 recoil에 dangerouslyAllowMutability: true,
값을 넣어주면 된다하여 넣었더니 되었다.. 이건 한번 알아봐야겠다.

아주 잘나온다!

profile
개발 재밌다

0개의 댓글