클론 하려 했는데 기획하게 된 React 개발 리뷰 (2)
5. Code Review
3) Creator Page 주요코드
- 위의 사진이 Creator Page가 완성된 모습이다.
- 사실 실제 클래스101의 크리에이터 페이지가 어떻게 생겼는지 난 아직도 잘 모른다.
아무나 크리에이터가 될 수는 있었으니 아무 상품이나 등록되는 것이 아니기 때문에.... 확인할 방법이 없었다. - 그저 내가 만든 클래스가 상품이 되고, 강의가 되어야 한다는 것에 목적을 두고 직접 기획해서 만들기 시작했다.
- 위 사진은 클래스101의 크리에이터 센터 라는 곳이다. 이곳의 디자인을 참고해서 꾸며보았다.
(1) Creator.js
: 최상위 부모로 전체 레이아웃 틀이 존재하며 모든 통신이 발생되는 곳이다.
// Creator.js
const [selectedPage, setSelectedPage] = useState(0);
const [selectedCategory, setSelectedCategory] = useState('');
const [selectedSubCategory, setSelectedSubCategory] = useState('');
const [selectedDifficulty, setSelectedDifficulty] = useState('');
const [selectedClassName, setSelectedClassName] = useState('');
const [selectedPrice, setSelectedPrice] = useState('');
const [selectedDiscount, setSelectedDiscount] = useState('');
const [uploadFirstImage, setUploadFirstImage] = useState();
const [files, setFiles] = useState([]);
const [selectedLecture, setSelectedLecture] = useState([{}]);
const [lecturefiles, setLecturefiles] = useState([]);
const [makeLecture, setMakeLecture] = useState([]);
const [lectureImage, setLectureImage] = useState([]);
const [lectureVideo, setLectureVideo] = useState([]);
const [kitnames, setKitnames] = useState([]);
const [kitImage, setKitImage] = useState([]);
- 강의에 들어가는 자료들이 너무 너무 많다. 그 때문에 State도 위와 같이 어마어마하게 많다. 수많은 자식 컴포넌트가 있고, 손자, 증손자가 존재한다. 그때의 통신을 위한 데이터가 이곳으로 모이게 되어있다.
- 리덕스를 배우기전이라 최상위 부모인 이 Creator가 이 모든 것을 관리하고 통신하고 있다.
- 때문에 이것을 통신하는 Fetch 함수가 수도 없이 많이 존재하고 있다.(반복 코드이니 생략)
if (selectedPage === 0) {
const temp = JSON.stringify({
categoryName: selectedCategory,
subCategoryName: selectedSubCategory,
difficultyName: selectedDifficulty,
name: selectedClassName,
price: selectedPrice,
sale: selectedDiscount / 100,
});
let formData = new FormData();
formData.append('body', temp);
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i]);
}
formData.append('files', files);
fetch('API', {
headers: {
authorization: localStorage.getItem('token'),
},
method: 'POST',
body: formData,
})
.then((res) => res.json())
.then((result) => {
console.log(result);
});
} else if (selectedPage === 1) { /* 생략 */ }
- 이런식으로 페이지 마다의 통신이 이루어진다.
if (selectedPage === 0) { blabla }
- 이때 위에서처럼 재밌는 방법으로 통신을 시도해보았다. 페이지 넘버를 스테이트 값에 넣고 그 값에 따라 통신 코드를 달리 보내게 만들어두었다.
const temp = JSON.stringify({
categoryName: selectedCategory,
subCategoryName: selectedSubCategory,
difficultyName: selectedDifficulty,
name: selectedClassName,
price: selectedPrice,
sale: selectedDiscount / 100,
})
formData.append('body', temp);
- 강의 설명등은 Json 텍스트 형태로 변형하여 FormData에 담아 전송하였고
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i]);
}
- 이미지와 영상 등은 File 의 원본 형태(MultiPart)로 FormData로 담아 전송하였다.
- 여기서 재밌는 코드가
FormData
의하나의 키 값
에 append를 이용해서어떻게 하면 여러 데이터를 담을 수 있을까??
를 연구하다가... 그냥 반복문을 써서 한개의 키값에 계속 담으면 다 담아지더라!
// 렌더 부분 일부
{selectedPage === 0 ? (
<Introduce
getSelectedCategory={(e) =>
setSelectedCategory(e.target.value)}
getSelectedSubCategory={(e) =>
setSelectedSubCategory(e.target.value)}
getSelectedDifficulty={(e) =>
setSelectedDifficulty(e.target.value)}
getSelectedClassName={(e) =>
setSelectedClassName(e.target.value)}
getSelectedPrice={(e) =>
setSelectedPrice(e.target.value)}
getSelectedDiscount={(e) =>
setSelectedDiscount(e.target.value)}
getFirstImage={(e) => setUploadFirstImage(e)}
getUploadImage={(file) => setFiles(file)}
/>
) : null}
- 스테이트를 이렇게 관리하면 자식 컴포넌트와 주고 받는 데이터가 어마어마하다. 리덕스가 반드시 필요해보인다.(당장 리펙토링이 필요해)
(2) Introduce.js
: 여기서는 강의를 상품으로 등록하는 페이지다.
상품 리스트와 상품 디테일 페이지에 보여줄 데이터를 input 하게 된다.
여기서 주요 코드는 상품 대표사진 3장을 담아야 하는 부분인데, 총 3개의 파일을 업로드 해야 하지만 한번에 3개의 파일을 다 담지 않고 1개씩 3번을 담아야하기 때문에 Form에 multiple 속성을 넣을 필요 없고 Form이 3개 필요했다.
function onFileUpload(event) {
let file = event.target.files[0];
setFiles([...files, file]);
}
- 이때 업로드된 이미지와 미리보기 이미지는 별도의 함수를 작성했다.
위의 코드는 파일의 원본 형태로 State에 담는 함수이다.
const upLoadImage = (e) => {
let reader = new FileReader();
if (e.target.files[0]) {
reader.readAsDataURL(e.target.files[0]);
reader.onloadend = () => {
const imageUrl = reader.result;
setfirstUploadImage(imageUrl.toString());
props.getFirstImage(imageUrl.toString());
};
}
};
- 위의 코드는 파일의 미리보기를 위해
FileReader()
를 불러오는 함수이다
// 렌더 부분
<FirstForm method='post' encType='multipart/form-data'>
<FirstLabel htmlFor='firstUpLoad'>
<img
src={ firstUploadImage ? firstUploadImage : '/images/SH/noImage.png'}
alt='noimage' />
</FirstLabel>
<FirstInput
type='file'
id='firstUpLoad'
onChange={(e) => {
onFileUpload(e);
upLoadFirstImage(e);
}}
/>
</FirstForm>
- 여기서 재밌는 점은 input의 라벨을 클릭하도록 만들었다. 그리고 그 라벨을 이미지로 만들어버렸다. 그리하면 라벨의 이미지를 클릭하면 파일 첨부창이 뜨게 된다.
(원래 보통 이렇게 하는지는 잘 모르겠다)
이제 3부에서는 상품이 아닌 강의를 직접 만들러 가보자
Author And Source
이 문제에 관하여(클론 하려 했는데 기획하게 된 React 개발 리뷰 (2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@xedni/클나스2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)