# usePagination - composition api (vue2)

### 이슈 1. 반복 코드 리팩토링&#x20;

Pagination 컴포넌트를 사용하는 곳에서 공통으로 반복해서 사용하는 코드를 composition api 를 사용하여 개선해보았습니다.

#### 기존 공통 코드&#x20;

```typescript
export default Vue.extend({
  data: () => ({
    pageOptions: {
      page: 1,
      size: 10,
      totalElements: 0,
      totalPages: 0,
      first: false,
      last: false,
    },
  }),
  ...
  methods: {
    async getNotice() {
      try {
        const response = await notice_api.getNotice(config);
        if (response.status === 200) {
          const data = response.data.items;
          this.pageOptions = {
            page: this.pageOptions.page,
            size: data.size,
            totalElements: data.totalElements,
            totalPages: data.totalPages,
            first: data.first,
            last: data.last,
          };

```

### 개선 코드&#x20;

> hooks/usePagination.ts

공통으로 사용할 data와 function을 관리&#x20;

```typescript
import { reactive } from "@vue/composition-api";

export interface PageType {
  page: number;
  size: number;
  totalElements?: number;
  totalPages: number;
  first: boolean;
  last: boolean;
}

interface ArgType {
  size: number;
}
interface ReturnType {
  pageOptions: PageType;
  setPageOptions: (page: number, response: PageType) => void;
}

// 한번에 보여줄 리스트 갯수(size)를 argument로 전달하고, 기본값은 10. optional로 생략가능 
export const usePagination = (arg?: ArgType): ReturnType => {
  const pageOptions = reactive<PageType>({
    page: 1,
    size: arg?.size || 10,
    totalElements: 0,
    totalPages: 0,
    first: false,
    last: false,
  });
  const setPageOptions = (page: number, response: PageType) => {
    pageOptions.page = page;
    pageOptions.size = response.size;
    pageOptions.totalElements = response.totalElements;
    pageOptions.totalPages = response.totalPages;
    pageOptions.first = response.first;
    pageOptions.last = response.last;
  };

  return { pageOptions, setPageOptions };
};

```

> 사용 예&#x20;

```typescript
import { usePagination } from "@/hooks/usePagination"; 

export default Vue.extend({ // 이슈 2. 에서 수정!
  setup() {
    const { pageOptions, setPageOptions } = usePagination();
    return { pageOptions, setPageOptions };
  },
  ...
  methods: {
    async getNotice() {
      try {
        const response = await notice_api.getNotice(config);
        if (response.status === 200) {
          const data = response.data.items;
          this.setPageOptions(this.pageOptions.page, data); 
  
```

> 한번에 보여줄 리스트 갯수(size) 조절시 예&#x20;

```typescript
const { pageOptions, setPageOptions } = usePagination({size: 5});
```

###

### 이슈 2. typescript: property does not exist on type 'object & record\<never, any>

* setup() 에서 return한 데이터를 `<template>` 코드 내에서 사용시 기능은 모두 동작하였으나, 위와 같은 빨간줄 typescript 경고가 생겼습니다.
* 테스트해보니 chrome vue extention 에서도 data로 잘 들어오고 있고, build 에러도 뜨지 않았지만, 찾아보니 아래와 같이 수정을 하면 typescript 경고가 발생하지 않았습니다.

#### 참고 자료

* Vue 3로 마이그레이션하기 위해 준비해야 할 것: <https://ui.toast.com/weekly-pick/ko_20200804>
  * [`defineComponent`를 이용하여 Vue 컴포넌트를 초기화하도록 변경한다.](https://ui.toast.com/weekly-pick/ko_20200804#%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%A0-%EB%95%8C-vuecomposition-api%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C%EB%8B%A4)

### 해결 코드&#x20;

```typescript
<template>
  ... 
  // 이제 빨간 경고 줄이 생기지 않습니다. 
  <Pagination :pageOptions="pageOptions" @click="onClickPage" />
</template>

<script lang="ts">
import { defineComponent } from "@vue/composition-api";

export default defineComponent({
  setup() {
    const { pageOptions, setPageOptions } = usePagination();
    return { pageOptions, setPageOptions };
  },
```

### **Pagination 2개 이상 사용시 코드 비교**&#x20;

> **composition api 사용 전**&#x20;

```typescript
data: () => ({
    pageOptionsHistory: {
      page: 1,
      size: 5,
      totalElements: 0,
      totalPages: 0,
      first: false,
      last: false,
    },
    pageOptionsGroup: {
      page: 1,
      size: 5,
      totalElements: 0,
      totalPages: 0,
      first: false,
      last: false,
    },
  }),
...
  methods: {
    async getHistory() {
      try {
        const response = await notice_api.getHistory(config);
        if (response.status === 200) {
          const data = response.data.items;
          this.pageOptionsHistory = {
            page: this.pageOptionsHistory.page,
            size: data.size,
            totalElements: data.totalElements,
            totalPages: data.totalPages,
            first: data.first,
            last: data.last,
          };
        ...
    async getGroup() {
      try {
        const response = await notice_api.getGroup(config);
        if (response.status === 200) {
          const data = response.data.items;
          this.pageOptionsGroup = {
            page: this.pageOptionsGroup.page,
            size: data.size,
            totalElements: data.totalElements,
            totalPages: data.totalPages,
            first: data.first,
            last: data.last,
          };
```

> **composition api 사용 후**&#x20;

```typescript
setup() {
    const {
      pageOptions: pageOptionsHistory,
      setPageOptions: setPageOptionsHistory,
    } = usePagination({ size: 5 });

    const {
      pageOptions: pageOptionsGroup,
      setPageOptions: setPageOptionsGroup,
    } = usePagination({ size: 5 });
    return {
      pageOptionsHistory,
      setPageOptionsHistory,
      pageOptionsGroup,
      setPageOptionsGroup,
    };
  },
...
  methods: {
    async getHistory() {
      try {
        const response = await notice_api.getHistory(config);
        if (response.status === 200) {
          const data = response.data.items;
          this.setPageOptionsHistory(this.pageOptionsHistory.page, data);
        ...
    async getGroup() {
      try {
        const response = await notice_api.getGroup(config);
        if (response.status === 200) {
          const data = response.data.items;
          this.setPageOptionsGroup(this.pageOptionsGroup.page, data);
```

이렇게 코드의 재사용성을 높여 반복 코드를 줄일 수 있습니다.&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sharryhong.gitbook.io/front-end/front-end-dev/vue.js/usepagination-composition-api-vue2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
