yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-11] 상위 컴포넌트에서 하위 컴포넌트의 상태(state)를 변경하는 방법 #190

Closed to06109 closed 1 year ago

to06109 commented 1 year ago

질문 작성자

최예송

문제 상황

이미지 업로드 페이지에서 이미지 업로드 인풋 컴포넌트를 사용하고, 삭제버튼을 클릭하면 이미지 업로드 인풋 컴포넌트의 미리보기를 초기화하는 기능을 구현하는 중에 갈피를 잡지 못해서 질문드립니다.

원래 제 코드에서는 ImageUploadInput 컴포넌트에서 file state를 관리하고 있고, 미리보기 이미지인 preview state는 file이 업데이트 될 때 결정되었습니다. 그리고 file state는 input에 파일이 들어왔을 때 업데이트 되었습니다. image image

이런 연관관계가 있어서 두 상태를 ImageUploadInput 컴포넌트에서 관리하도록 했었기 때문에 초기화 기능을 구현할 때 props drilling을 이용한 방법이 효율적이지 않다고 생각했는데, 이런 판단이 맞는지 궁금합니다!

일단은 UploadPage로 state를 끌어올려서(file, preview, onFileDrop을 props로 줬습니다) 미리보기를 지우는 것을 구현해 놓았는데 이 방법이 적절한 방법인지 궁금합니다. 이렇게하면 업로드 페이지의 코드가 너무 길어진다고 생각하는데 혹시 다른 방법이 있을까요? (이 코드는 feature/upload-UploadPage 브랜치의 b07db436 커밋입니다. )

프로젝트 저장소 URL

환경 정보

yamoo9 commented 1 year ago

문제 해결

React가 제공하는 useImperativeHandle 훅을 사용하면 하위 컴포넌트의 상태 변경을 상위 컴포넌트에서 수행할 수 있습니다. useImperativeHandle 훅은 forwardRef 고차 함수, useRef 훅과 함께 사용됩니다.

하위 컴포넌트에 추가할 코드

useImperativeHandle(fileInputRef, () => ({
  initFilePreview,
}));

const initFilePreview = () => {
  setPreview(null);
  setFile(null);
};

상위 컴포넌트에 추가할 코드

const imageInputRef = useRef(null);

const handleDelete = () => {
  imageInputRef.current.initFilePreview();
};
<ImageUploadInput ref={imageInputRef} />
<DeleteButton style={deleteButtonStyle} onClick={handleDelete} />

구현된 결과는 다음과 같습니다.

file-preview