OneBB Headless Forum refactoring
Tags: vue, opensource, typescript, beginners
Published: 2023-05-30 09:21:47

In this blog post, I will share how I refactoring onebb forum vue3 scripts from options to composition api. The composition api is a new feature in vue3 that allows us to write more modular and reusable code by grouping related logic together. It also has some benefits over the options api, such as better performance, easier testing, and cleaner code.

First of all, I changed VUECli to Vite, which is a faster and simpler tool for building vue applications. Vite uses native ES modules and provides features like hot module replacement, code splitting, and tree shaking. Vite also supports TypeScript, which I used for better type checking and code quality.

Next, I resigned to use Vuex and moved most of the logic to hooks for easier maintenance. Vuex is a state management library for vue, but it can be cumbersome to use with the composition api. Instead of Vuex, I used custom hooks to encapsulate the state and logic of each feature. Hooks are reusable functions that can use other vue features like reactive data, computed properties, and watchers.

For example, here is a hook that handles the api logic:

```js
const useApi = () => {
    const settings = {
        url: 'https://linktoonebb.com/api',
    }
    
    const options = {
        headers: {
            "Content-Type": "application/ld+json",
        }
    }

    const get = async <T>(endpoint: string, query?: string):Promise<T> => {
        const url = settings.url + endpoint + (query ? query : '');
        const response = await fetch(url, options);
        const jsonData:Promise<T> = await response.json();
        return jsonData;
    }

    const post = async <T, R>(endpoint: string, body: T):Promise<R> => {
        const url = settings.url + endpoint;
        const response = await fetch(url, {method: 'POST',  body: JSON.stringify(body), ...options});
        const jsonData:Promise<R> = await response.json();
        return jsonData;
    }

    return {
        get,
        post,

    }
}
export default useApi
```

As you can see, this hook exposes the API methods, in futeure they will also handle errors. I can use this hook in any component that needs to access or manipulate the API requests.

Finally, I refactored the components to use the composition api instead of the options api. The composition api provides a setup function where we can define the reactive data, computed properties, watchers, methods, and lifecycle hooks for each component. We can also import and use the hooks we created earlier.

For example, here is a component that displays categories list:

```vue
<script setup lang="ts">

import { defineProps, ref } from 'vue';
import Image from './ImageComponent.vue';
import { useUser } from '@/hooks/useUser';
import type { IBoard } from '@/interfaces/OnebbInterfaces';
import { useMoment } from '@/hooks/useMoment';

const props = defineProps<{
    board: IBoard
}>()

const { parseUsername } = useUser();
const moment = useMoment();
const last_active_user = ref();

if (props.board.last_active_user) {
    last_active_user.value = parseUsername(props.board.last_active_user)
}
const updated_at = moment.parse(props.board.updated_at);
</script>

<template>
    <div class="col-9">
        <router-link :to="{
            name: 'Board',
            params: { slug: board.slug, id: board.id, page: 1 },
        }">
            <span class="margin-s ">{{ board.name }}</span>
        </router-link>
    </div>
    <div v-if="board.last_active_user" class="col-3 row ">
        <div class="col-9 column text-align-end">
            <div v-html="last_active_user">
            </div>
            <div>
                {{ updated_at }}
            </div>
        </div>
        <div class="col-3 row align-items-center justify-content-flex-end">

            <Image :src="board.last_active_user.avatar" :alt="board.last_active_user.username" :size="[50, 50]" rounded />

        </div>
    </div>
</template>
```

As you can see, this component is much simpler and cleaner than using the options api. It also makes it easier to reuse.

All progress can be tracked on 
[Github Branch](https://github.com/pankrok/onebb/tree/front2.0-ts)

I hope this blog post was helpful for anyone who wants to think more about refactoring vue3 scripts from options to composition api. If you have any questions or feedback, please leave a comment below. Thanks for reading!

Forum script is avable to see here:
[OneBB Forum](https://onebb.org)