요구사항
- PostsPage : 기본 경로로 들어왔을 때 보여줄 컴포넌트. posts를 불러와서 렌더링하고, 클릭 시 해당 post를 수정하는 곳으로 이동함. 맨 아래에는 post를 생성할 수 있는 페이지로 이동하는 링크가 있음.
- PostEditPage : post를 생성하고 수정하는 페이지.
- url에 따른 라우팅 처리.
요점 정리
동작 원리
- main.js에서 App 생성자를 만든다.
- App.js는 세 가지의 일을 한다.
- postspage 컴포넌트 생성.
- route 컴포넌트로 url에 따라 어떤 페이지를 그리는지에 대한 로직.
- custom event를 통한 routing 처리.
- postpage.js에서 postlist와 linkButton 컴포넌트를 만든다. postpage 렌더링 시
fetchposts
를 불러옴.
- postEditpage.js는
- 로컬 스토리지에 임시로 넣은 값이 있는지 체크.
- editor 컴포넌트를 만듦. 입력이 생길 때마다
onEditing
으로 콜백으로 업데이트를 함. debounce를 이용해 업데이트 지연을 발생시킴.
- Editor.js는 title과 cotent의 값이 업데이트 될 때마
keyup
이벤트를 이용해 state를 바꾸고onEditing
을 호출함.
컴포넌트는 추상화를 잘 해야 함.
오류 찾기
this.state.map is not a function
과 같은 에러를 종종 볼 수 있음.
- validation, debugging, conosle.log로 차근차근 찾아보기
map에 배열이 안담긴건가? map에 어떤 값을 전달하고 있지?
→ PostPage.js에서 posts를 파라미터로 전달하네?
→ post를 console.log 찍어보니 함수가 나온다;; 왜 함수일까?
→ 아 json에 괄호를 안쳐주어서 함수를 반환했구나!
debounce
- 같은 이벤트를 반복시킨 후 가장 마지막에 발생한 이벤트만 실행시키는 기법.
- ex) 타이핑 간격이 길어질 때만 작성 중인 글을 저장하는 것.
- 로컬 스토리지에 데이터를 보내는 시간과 DB에 저장하는 시간을 분리해서 DB 저장시간을 좀 더 늦추면 효율적으로 데이터를 전송할 수 있음.
let timer = null; new Editor({ $target, initialState: { title: "today we are going to", content: "JS", }, onEditing: (post) => { clearTimeout(timer); timer = setTimeout(() => { setItem("temp-post", { ...post, tempSaveData: new Date(), }); }, 500); }, });
- 입력을 연속으로 할 때는 이벤트 발생을 지연시키다가, 입력을 멈췄을 때(마지막으로 이벤트가 발생하고 일정 시간이 지났을 때) 지연시켰던 이벤트를 실행시킴.
- 이벤트 발생 횟수를 줄여 성능이나 최적화 관점에서 좋음.
- 키워드 :
clearTimeout
,setTimeout
SPA Routing
- 로딩 시 생기는 빈 화면에 대한 시간을 줄이기 위해 SPA와 함께 라우팅이 사용됨.
- 초기 애플리케이션을 로드할 때 모든 웹 사이트 콘텐츠를 로드하고 URL 경로 이름에 따라 페이지에 올바른 콘텐츠를 동적으로 표현
- SPA 라우팅을 구현하는 2가지 방법
history (Browser History)
: history.pushState API를 활용하여 페이지를 다시 로드하지 않고 URL을 탐hash (Hash History)
: url 해쉬를 사용하여 전체 url을 시뮬레이트하게되며, url이 변경될 때 페이지가 다시 로드되지 않음. 보통 url에 #이 붙음.
custom event
- 특정한 상황에서 이벤트에 데이터를 씀으로써 depth를 무시하고 global하게 쓸 수 있는 장점.
- 남용하면 이벤트가 언제 생길지 일일히 파악해야 하기 때문에 디버깅이 어려울 수도 있음.
export const push = (nextUrl) => { window.dispatchEvent( new CustomEvent("route-change", { detail: { nextUrl, }, }) ); };