평소 사용하던 class기반 컴포넌트 템플릿이 부모state변경 시에 모든 컴포넌트가 재렌더링 되는 구조였는데, 이번 과제는 keyup이벤트를 사용해야했고, input값이 변경될 때마다 input도 재렌더링이 되는 문제점이 생겼다. 결국 템플릿 사용을 포기하고 특정 자식만 재렌더링 되도록 코드를 수정하느라
쓸데없는 시간이 들어서 기능을 많이 구현하지 못했다.. 클래스 확장의 편리함과 부분 렌더링을 모두 가져가는 컴포넌트 구조를 많이 고민해봤지만 답이 안나와서 전부 재렌더링되지만 편리한 방법을 가져갔는데
걸림돌이 되었다.. 좀 더 고민해볼걸 그랬다
테스트를 마치고 어떻게 하면 두 기능을 다 가져갈지 이것저것 시도해봤는데 결국 방법을 생각해냈다
export default class ProductDetailPage extends Component {
$selectedOptions;
$select;
...
createSelectedOptionsComponent() {
const $selectedOptions = this.$target.querySelector(
'.ProductDetail__selectedOptions',
);
const { productData, selectedOption } = this.state;
const { productPrice } = productData;
this.$selectedOptions = new SelectedOptions($selectedOptions, {
productPrice,
selectedOption,
onChange: this.handleChangeInput.bind(this),
onSubmit: this.handleSubmit.bind(this),
});
}
mounted() {
if (!this.state) {
return;
}
this.createSelectComponent();
this.createSelectedOptionsComponent();
}
reRender() {
const { selectedOption } = this.state;
this.$selectedOptions.setState({
selectedOption,
});
}
// template/Component.js
render() {
this.$target.innerHTML = this.template();
this.mounted();
}
reRender() {
// 특정 자식 컴포넌트만 렌더링 시키는 코드(setState꺼내서 실행)
}
setState(newState, reRender = false) {
this.state = { ...this.state, ...newState };
reRender ? this.reRender() : this.render();
}
동적으로 바뀌는 돔은 컴포넌트로, 바뀌지 않는 돔은 template literal로 작성하면된다!
이 방법이면 클래스 확장의 편리함과 부분 렌더링을 모두 가져갈 수 있다!
클래스에 대한 이해가 부족해서 별 거 아닌데 많이 해멘 것 같다..
메소드에서 변수를 쓰려면 무조건 전역 프로퍼티를 먼저 선언해줘야한다는 건 알았는데
construtor함수 안에서만 가능한 줄 알았다..
이번 과제가 공개되면 3시간 잡고 다시 풀어봐야겠다.
provider: 값 제공(생성)
hook: 값을 받아서 가공 후 반환, 컨텍스트 받는 처리해주어 컴포넌트에서 간단하게 사용할 수 있게 함
component: hook에서 반환한 값을 받아서 렌더링
모달 창 오픈 시 애니메이션 중지
modalProvider에서 모달 열리고 닫히는 isOpen상태값 추가,
cardList 컴포넌트에 불러와 useEfferct에 isOpen상태를 의존으로 걸어주어
ture일 경우 애니메이션 재생, false일 경우 중지 되게 구현
useEffect(() => {
isOpen ? setIsPlayMove(false) : setIsPlayMove(true);
}, [isOpen]);
Tab이 바뀔 때마다 animation새로 실행되도록 구현
→ Tab의 type을 의존으로 걸어 준 후 스크롤을 가장 앞으로 당겼다
각 tab마다 스크롤을 기억해놓고 싶지만 같은 dom을 쓰기 때문에 불가능할 것 같은데 더 생각해봐야겠다
const handleClickFrontButton = useCallback(() => {
if (containerDom instanceof Element) {
containerDom.scrollLeft = 0;
setIsPlayMove(true);
}
}, [containerDom]);
useEffect(() => {
handleClickFrontButton();
}, [handleClickFrontButton, resetDep]); // resetDep === tab의 type
custom hook에 typescript사용
카드 리스트 애니메이션 관련 로직들을 hook으로 분리했다
custom hook사용 시 리턴 타입을 지정해줘야 한다
type ReturnTypes = [() => void, () => void, (on: boolean) => void];