this.init = () => {
const $history = document.createElement('ul')
$history.id = 'histories'
const $searchForm = document.createElement('form')
$searchForm.id = 'form-search'
$searchForm.addEventListener('submit', (e) => e.preventDefault())
const $searchResults = document.createElement('ul')
$searchResults.id = 'search-results'
this.components = [
new SearchForm({
$target: $searchForm,
setSearchResults: this.setState.bind(this),
}),
new SearchResult({ state: this.state, $target: $searchResults }),
]
this.$root.appendChild($history)
this.$root.appendChild($searchForm)
this.$root.appendChild($searchResults)
}
this.setState = (arg) => {
let newState = isFunction(arg) ? arg(this.state) : { ...this.state, ...arg }
validateSearchResults(newState.searchResults)
this.state = newState
this.render()
}
익명함수는 typeof
나 instanceof
로 체크가 불가능 GeeksforGeeks 사이트에서 object.prototype.toString
를 사용해서 해결했다!
export const isFunction = (fn) => {
return Object.prototype.toString.call(fn) === '[object Function]'
}
App이라는 상위컴포넌트에서 먼저 전체 state 유효성 검사를 실시한 후 하위컴포넌트의 setState 함수를 호출하여 rendering하는 방식으로 구현했습니다. 혹시나 하위컴포넌트의 setState를 직접 사용할 것을 대비하여 하위컴포넌트의 setState에서도 받아오는 인자값 유효성 검사를 하도록 구현했습니다. 이렇게 되면 상위컴포넌트에 의해 하위컴포넌트의 setState가 호출될 경우 불필요한 타입체크를 한 번 더 하게 됩니다. 하위컴포넌트만 유효성 검사를 하자니 state를 보관하는 건 App이고 App에서 유효성 검사 없이 값을 저장해두면 기존에 정상적인 데이터에 영향이 갈까봐 App에서도 남겨야 한다고 생각을 했습니다. 이럴 경우 어떤 식으로 최적화를 할 수 있을까요?
처음엔 짧게 무엇을 구현했다고만 서술했지만 다른 분들의 PR을 확인하면서 보는 입장에서는 코드를 같이 첨부하면서 이부분을 이런 식으로 구현했다고 설명하는 게 이해하기 쉽다는 것을 알게 되었다. 3번째 PR때는 아래와 같이 길게 작성하게 되었다.
api로부터 받은 데이터를 그저 data로만 적으면 데이터가 하나의 객체인지 , 여러 개 들어있는 배열인지 바로 파악하기 어렵기 때문에 검색해서 받은 결과들이라는 뜻으로 SearchResults 를 썼다. 좀 더 자세히 적으려면 움짤이기 때문에 gifImages 라고 하는 게 더 명확한 것 같다!
fetch 요청하는 부분을 api.js로 분리하고 debounce하는 부분은 utils.js로 분리하면서 기능을 세분화하는 작업을 통해 코드가 점차 간결해지고 정리되는 것을 느꼈다!