지금까지 만든 페이지 네이션을 사용하려면
상품페이지 가면 상품페이지네이션이
마이페이지 가면 마이페이지네이션이
페이지 마다 똑같은 페이지네이션을 만들어야 하는데 비효율적임안의 내용물은 달라도 페이지 네이션은 동일한 것
하나를 잘 만들어서 여기저기 쓸 수 있게 해보자.
자식1의 state를 count라고 했을때
자식1에서 count를 올렸을 때 자식 2에서도 보이고 싶다.
부모 자식이면 props로 넘기면 가능한데
형제끼리는 어떻게하면 좋을까.
이 때 사용하는게 state를 끌어올리는것.
count, setCount를 부모로 옮겨서 부모는 자식에게 넘길 수 있으니
양쪽에 전달하는 방식
이렇게 되면 자식 1에서 값이 바뀌면 자식 2에도 같이 바뀌게 됨.
버튼은 자식에 있음
자식의 버튼을 누르면 부모의 state가 올라가도록 만들어야함.
지금껏 state는 부모에서 자식에게 주는 단방향 이라고 배웠음부모의 setState를 props로 보내주면 가능해짐
부모에게서 받아온 setState를 바꿔주면 어쨋든 부모의 state이기 때문에
부모의 state값이 바뀌게됨
바뀐 state가 props를 통해서 다시 내려오게됨.
부모와 자식2개를 따로 만들어주고
- setCount 보내기
// 부모 코드 <Child1 count={count} setCount={setCount}></Child1> // 자식 코드 function onClickCountUp () :void { props.setCount((prev : number) => prev + 1) } <button onClick={onClickCountUp}>카운트 올리기</button>부모에서 자식으로 setCount를 보내고 자식에서 setCount로 함수를 만들어서 사용
2. 함수 보내기// 부모 코드 const onClickCount =() :void => { setCount((prev : number) => prev + 1) } <Child2 count={count} onClickCount={onClickCount}></Child2> // 자식 코드 <button onClick={props.onClickCount}>카운트 올리기</button>부모에서 함수를 만들어서 자식으로 보내서 사용
둘 모두 동일하게 연동되어 동작함
1번을 눌러도 2번을 눌러도 같이 오름
위에서 child 1이 게시글 목록이면
child 2 가 페이지 네이션으로 사용다른 페이지에서는
child 1이 상품목록
child 2가 다시 페이지 네이션이런식으로 사용하면 많은 페이지에서 페이지 네이션은 하나로 반복 사용이 가능함.
부모 페이지
// 보드 목록 전부 가져오기 const FETCH_BOARDS = gql` query getBoards($page: Int) { getBoards(page: $page){ id writer title contents } } ` // 보드 갯수 가져오기 const COUNT_BOARDS = gql` query { getBoardsCount } ` export default function PaginationRefactoringPage() { // 보드 목록을 data에 저장 const { data, refetch } = useQuery<Pick<IQuery,"getBoards">,IQueryGetBoardsArgs>(FETCH_BOARDS) // 보드 갯수 가져와서 dataBoardsCount에 저장 const {data:dataBoardsCount} = useQuery<Pick<IQuery,"getBoardsCount">,String>(COUNT_BOARDS) // 최대 몇페이지까지 만들지 저장 const lastPage = Math.ceil ((Number(dataBoardsCount?.getBoardsCount )?? 10) / 10 ); return ( <> {/* 보드 리스트 */} <BoardList data={data}></BoardList> {/* 페이지 네이션 */} <PageNation refetch={refetch} lastPage={lastPage}></PageNation> </> ) }쿼리 부분만 부모페이지에 남기고, 나오는 데이터는 각각 자식에게 넘김
자식2 : 페이지 네이션
export default function PageNation(props:IPageNationProps):JSX.Element{ // 현재 페이지 세트 계산할 startPage const [startPage, setStartPage] = useState(1); const onClickPage = (event:MouseEvent<HTMLSpanElement>): void => { void props.refetch({page: Number(event.currentTarget.id)}) } const onclickPrevPage = ():void => { if(startPage === 1) return; setStartPage(startPage - 10) void props.refetch({page: startPage - 10}) } const onclickNextPage = () :void => { if(startPage + 10 > props.lastPage) return; setStartPage(startPage + 10) void props.refetch({page: startPage + 10}) } return( <> <span onClick={onclickPrevPage}>이전 페이지</span> { new Array(10).fill(1).map((_,index) => index + startPage <= props.lastPage && (<span key={index + startPage} id={String(index + startPage)} onClick={onClickPage}> {index + startPage} </span>) )} <span onClick={onclickNextPage}>다음 페이지</span> </> ) }부모에게서 받은 lastPage를 통해서 최대 페이지를 정하고
페이지 네이션을 만들고 현재 화면에 몇페이지를 띄우는지
props.refetch를 통해서 page값을 부모에게 보냄부모는 받아온 page를 쿼리로 보내서 현재 보드의 목록을 data로 저장해서
자식1로 보냄자식1 : 보드 목록
export default function BoardList(props : IBoardListProps) :JSX.Element { return ( <div> {props.data?.getBoards?.map(el => ( <div key={el?.id}> <span style={{ margin: "15px", padding: "0px" }}>{el?.title}</span> <span style={{ margin: "15px" }}>{el?.writer}</span> </div> ))} </div> ) }받아온 게시글 목록을 출력함.