Vuejs composables: hands-on examples
Tags: vue, webdev, frontend, javascript
Published: 2023-08-15 21:38:23

Composition API'S was introduced in vue from 2.7 version to replace options API'S. 

On of These API's is **Reactivity api**  (`'ref'` and `'reactive'`) to declare reactive state, instead of data function in option API. 

This new API is the backbone of **composables**.
<br>
*********
##What are composables?
Composables are functions based on reactivity api following a specific structure making it possible for developers to **_separate_** stateful or stateless logic from components.



In addition, logic itself could be split in different composables and nested together to achieve a specific task on account of the fact that composables are _'malleable'_ through arguments.
<br>
***
##Composables examples:
Composable have three major parts:

**_Internal state:_** Any state related to the function. 
States that will be exposed must be reactive using `'ref'` or `'reactive'`.

Nevertheless, it is recommended to use `'ref'` since it retains reactivity and enables destructuring in components straightforward compared to `'reactive'`. 

**_Manage state:_** A logic to apply when an action happens

**_Return state:_** Expose managed state

Composable returns an object with single value or multiple values, a value could be a method.
 
<br>
### 1. Basic composable

In the example below _`useIsUserActive`_ is a composable to check if a user click somewhere in the page.
  <figcaption>Basic composable example: useIsUserActive</figcaption>


![composable example1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ci3ct3ttuhjmokb0xep.png)


Then imported and executed in vue component.
  <figcaption>Basic composable example: useIsUserActive called in component</figcaption>
![composable example1-template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/560yic5wtn0dww6k9ytj.png)
You may notice that composable name starts with `use` as it is the naming convention from vuejs team.
<br>
### 2.Composable with returned methods: 

Let's see more sophisticated example: `useTimer`

This composable will act as a timer that we can control through different methods: `start`, `pause` and `stop`.


 <figcaption>useTimer example</figcaption>
![composable example2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nve9ffowps872igvzgf.png)

 <figcaption>useTimer composable called in component</figcaption>

![composable example2-template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5cmwtt296eqcemr8lnvg.png)

<br>
### 3.Composable with arguments:

Composable could be parametrized as the example below.

This composable is responsible for replacing spaces in strings with specific separator.
 <figcaption>useFormatString example</figcaption>

![composable example3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qy5gay48urg6xobh3ovu.png)

 <figcaption>useFormatString called in component</figcaption>

![composable example3-template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9a4sc1927s3jr23aos0j.png)
- `data` and `separator` are the parameters. 

- `watchEffect` will be run whenever one of its dependencies change. Without `watchEffect` our function will run only the first time even though `data` or `separator` have been changed. 
Its dependencies must be reactive to be capable of doing this job, for that reason `data` and `separator` must be a ref.

- `toValue` is a function that returns either:

  &nbsp;&nbsp;&nbsp;&nbsp; 1.Normalized `value` of the source if that source is a `ref`.

 &nbsp;&nbsp;&nbsp;&nbsp;  2.Execute the function of the source and returns its value if 
     that source is a getter function.

  &nbsp;&nbsp;&nbsp;&nbsp; 3.Returns `value` of the source if that source is a normalized 
    value. 

<br>
***
## Composables advantages:

Let's use `useTimer` composable logic straight inside the component. 

```ts
<script setup lang="ts">
import { ref } from "vue"

const timer = ref(0)
let myInterval: number

// start method
const start = () => {
  myInterval = setInterval(() => {
    timer.value = timer.value + 1
  }, 1000)
}

// pause method
const pause = () => {
  clearInterval(myInterval)
}

// stop method
const stop = () => {
  timer.value = 0
  clearInterval(myInterval)
}
</script>

<template>
  <main>
    {{ timer }}

    <button @click="start()">start</button>
    <button @click="pause()">pause</button>
    <button @click="stop()">stop</button>
  </main>
</template>
```

- You will notice that the component does not care of timer state, then it does not make any sense for the component to have access to timer logic.

- You will not be capable of reuse this logic unless you copy paste.

- Imagine this component get bigger, it will be more difficult to debug.

As you may notice this technique will offer **_lighter_** components regarding components **_complexity_** and **_length_**. Besides easier **_debugging_**.
<br>
***
## Conclusion:

Composables are the new way of **_reuse_** and **_encapsulate_** logic in vuejs application. They gain this power from _composition api_ the thing that take vuejs application to another level. 

Implementing composables, from personal use in several projects, won't cost neither ambiguity nor new layer of complexity compared to their advantages.


You find the examples above in my github: [Github](https://github.com/hssanbzlm/vue-composables)