오늘 수업한 중점적인 내용은 페이지네이션이다.
페이지 네이션이란,댓글이나 어떤 글을 볼때 스크롤로 막 내려보는것, 그리고 페이지를 선택하는 것 등이 있다.
오늘 한것은 버튼을 눌러 페이지를 옮기는 것이었다.
먼저, 일단은 벡엔드에서 게시판들 목록 데이터를 받아와 그려준다.
페이지를 정해주지않으면 기본으로 나오는페이지는 1페이지이다.
첫번째 페이지만 나오는데, 그럼 어떻게 다음페이지를 보느냐.
이럴때 페이지 네이션을 사용한다.
한번에 그려줄때 열개씩 그려지게되므로, 1페이지당 한면이 그려진다.
일단 배열에 10 페이지씩 들어가게 만들어주었다.
그러면 딱 10페이지의 정도만 볼 수 있다.
그렇다면 나머지 페이지는?
여기서는 map을 많이 사용했다.
데이터를 불러와 게시판을 그려줄때, 그리고 페이지들을 그려줄때.
우리는 map을 사용하여 각 요소를 불러올 수 있었다. 그렇지만 이 요소들의 값으로는 페이지를 딱 그정도만 그려줄 수 있고, 배열 선언이 필요하다. 그런데, index를 사용한다면 궂이 우리가 배열을 만들어줄 필요는 없다.
우선 new Array로 새 배열을 만드는데, new Array(10)으로하면 빈배열에 10자리가 만들어진다.
거기에 .fill(1)을 사용하여 1로 배열을 채우는데, 어차피 인덱스를 사용할 것이라 어떤 숫자로 채우든 상관없다.
그다음, 첫페이지 에서는 1부터 10까지의 페이지가 보이기를 원하니, index+1이라는 것을 이용해 맵을 돌려주고,
이전버튼과 다음버튼을 만들어 그 다음 페이지들10개, 그전 페이지 10개씩을 볼 수 있게 설정한다. onClick 함수에 setState(state+10), setState(state-10) 이렇게 주게되면 각 이전페이지를 누르면 이전의 10개, 다음을 누르면 다음페이지 10개가 나오게 되는것이다.
그런데, 문제가 발생했다.
다음버튼을 눌렀는데 아무 내용도 없는 페이지도 나오고, 이전버튼을 눌렀을때 -페이지가 나오는 것이다.
그래서 조건문이 필요했다.
만약 페이지 수가 1이면 더이상 페이지가 줄어들지 않게 막아 이전버튼의 문제는 해결되었다.
그럼 다음 버튼에서 무한히 나오는게 문제가되었다.
딱 마지막페이지까지만 나와야하기에 마지막페이지를 구해야하는데, 그러기위해서 전체 개시글 수가 필요하다.
우리가 원하는 결과는 만야약 개시글이 13개면 2페이지 123개이면 13페이지 가 필요한것인데,(한부분당 10페이지씩 나오기에) 그렇다면 개시글 수를 10으로 나누어 반올림함수 Math.ceil을 사용해 마지막페이지가될 수를 구한다.
그럼 만약 setState(state+10)한것이 마지막페이지보다 작거나 같을때만 10페이지씩 보여주게하고 아닐경우 빈태그하나를 넣어주어 나머지는 안보이게 처리하거나, 아니면 아예 if절만 사용하여 조건에 안맞는 나머지는 무시하고 그려주지않게하는 두가지 방법중 하나를 사용하면 페이지가 완성된다. 이 페이지 네이션만 따로 컴포넌트에 담아 유용하게 여러페이지에서 사용할 수 있다.
11/18일
무한스크롤생성을 만들어보기전에 객체나 배열의 복사에대해 배웠다.
기존의 let aaa = "철수"
let bbb = aaa
해서 bbb와 aaa를 찍어보면 둘다 철수가 나오고,
이 경우는 둘중하나의 값만 변경해 할당해줘도 둘이 연결되어있지 않기에 만약 aaa의 값이 "유리"로 바뀐다고 하더라도 bbb의 값까지는 바뀌지 않는다.(call by value =값을 요청한다)
그러나 객체나 배열의 경우는 다르다.
이 경우에는 복사는 된다고해도(엄밀히 말하면 복사가 아니라하셨지만..)한쪽의 값을 바꿔도 다른쪽의 값또한 바뀌는 기상천외한 일이 벌어진다.
왜냐, 둘은 값을 바로 데려와 복사하는게 아니라 그 값이 있는 위치 즉, 주소를 가지고있어 그 주소가 복사되기에 벌어지는 현상이다.(call by reference = 주소를 받아온다.)
따라서 아예 새 객체를 만들어(다른주소가 필요하기에) 넣어주어야하는데 두가지 방법이 있다.
중괄호 이용하기.
중괄호를 이용한다는것은 말그대로 객체를 만들어주는것이다.
만약 const profile = { name: "철수", age: 12 }
를 복사해오려고 한다면
const profile2 = { name: profile.name, age: profile.age }
이런식으로 일일이 적어주어야한다.
그런데 저 내용물 부분은 한단어로 축약이 가능하다. 바로 스프레드 연산자인 (...)를 이용하는 것이다.
const profile2 = {...profile}
이렇게 간단하게 표현이 가능하다. 그러면 완벽하게 복사된것처럼 보인다. 엄연히 새 객체(또는 배열)을 만듦으로 서로 값들은 같지만 다른 주소를 가지게 변경할 수 있었기 때문이다. 이것을 얕은복사:(shallow copy)
다만, 이렇게 되어도 객체안에 또다른 객체가 존재한다면 그것또한 주소를 가지기에 또 문제가 된다.
따라서 이럴 경우에는
JSON.strigify()를 이용해 문자열로 풀어주고,
JSON.parse()로 원본으로 다시 바꿔주는 것이다.
const profile = { name:"철수", hobby:{ hobby1:"수영", hobby2:"산책" } }
JSON.stringify(profile) {"name":"철수","hobby":{"hobby1":"수영","hobby2":"산책"}}
const profile2 = JSON.parse(JSON.stringify(profile))
profile2 { name:"철수", hobby:{ hobby1:"수영", hobby2:"산책" } }
이런식의 복사를 깊은 복사 deepCopy라고하며 참고로 이렇게 복사를 해주는 라이브러리도 존재한다고한다.
이러한 복사를 어디에쓰나 보니까, 벡엔드에서 받아오는 데이터는 배열안의 객체의 형태라는 사실이 기억이 났다.
스크롤 페이지네이션 즉, 무한 스크롤에 이용을 해보자.
먼저 10개가 보여지고 그후에 10개씩 한페이지들이 합쳐지는 형태이다.
그럼 처음 열개와 그다음것 합치기!
스프레드 연산자를 이용한다.
const ccc = [...aaa,...bbb]
이렇게 사용한다면 ccc의 배열에 aaa와 bbb가 합쳐진형태가 된다.
그리고 fetchMore이라는 아폴로 내장객체를 사용하는데, 1단계로 variables로 fetchMore요청하고,
2단계로 updateQuery를 하는 방식으로 진행되며 스크롤을 내릴때 fetchMore이 작동하고, variables로 받아온 데이터가 fetchMoreResult에 들어온다.
만댝 게시글이 더 없다면 기존것 까지만 불러온다.
React Infinite Scroller 라는 라이브러리를 사용하여 윈도우의 스크롤응 사용하는 방법과 자체의 스크롤을 이용하는 방법을 구현했다.
아래 사진은 자체의 스크롤을 적용하는 방법이다.
InfiniteScroll 안에 useWindow={false} 로 두고, style="height:700px;overflow:auto;"를 InfiniteScroll태그 바깥태그에 감싸도록 바꿔주며 박스안에서 스크롤이 움직이는 방식이다.