Reactivity Everywhere 

Master the Composable Pattern

Juan Andrés Núñez

Frontend Engineer

@juanwmedia

Juan Andrés Núñez

Content creator at

@juanwmedia

Hot topic 🌶

What is a composable?

a "composable" is a function that leverages Vue Composition API to compose and reuse stateful logic.

☑️ Reusability
☑️ Stateful logic
☑️ Composition

Async scenario

<script setup>
  import { ref } from "vue";
  const API_URL = 'https://thecatapi.com/get'
  const results = ref(null)

  try {
    const request = await fetch(API_URL)
    const results.value = await request.json()  
    doSomeStuffWithTheResults(results)
  } catch(err) {
    throw new Error(err.message)
  }
</script>

useAsync composable

import { ref, readonly } from "vue";

export function useAsync() {
  const results = ref(null);
  const error = ref(null);

  const makeRequest = async (API_URL) => {
    try {
      const request = await fetch(API_URL);
      const results = await request.json();
      results.value = results;
    } catch (err) {
      error.value = err;
    }
  };

  return {
    makeRequest,
    results: readonly(results),
    error,
  };
}

useAsync composable

import { ref, readonly } from "vue";

export function useAsync() {
  const results = ref(null);
  const error = ref(null);

  const makeRequest = async (API_URL) => {
    try {
      const request = await fetch(API_URL);
      const results = await request.json();
      results.value = results;
    } catch (err) {
      error.value = err;
    }
  };

  return {
    makeRequest,
    results: readonly(results),
    error,
  };
}
import { useAsync } from "./composables/useAsync";
const { result, error, makeRequest } = useAsync();

watchEffect(() => {
  if (result.value) doSomeStuffWithTheResults(results.value);
  if (error.value) throw new Error(error.value.message);
});

await makeRequest(API_URL);

Vue reactive API's outside components

import { ref, reactive } from "vue";

Let's write some composables 🔴

Stick to the basics

Scratch your own itch

Problem 1️⃣

Reuse logic

Tip 1️⃣

Start with the interface, not the implementation (IN / OUT).

✅ Reusability
☑️ Stateful logic
☑️ Composition

Problem 2️⃣

Maintaining state

useState pattern

import { reactive, readonly, toRefs } from 'vue';

// Like "data()" from Options API
let state = reactive({
  isDark: false,
});

export function useState(newState = {}) {
  const stateEntries = Object.entries(newState);
  if (stateEntries.length)
    for (const [key, value] of stateEntries) setState(key, value);

  function setState(property, value) {
    state[property] = value;
  }

  return {
    state: toRefs(readonly(state)),
    setState,
  };
}

Tip 2️⃣

You can toggle between a stateful or stateless composable in the blink of an eye.

✅ Reusability
✅ Stateful logic
☑️ Composition

Problem 3️⃣

Persisting state

Tip 3️⃣

Compose composables

One composable can call another composable: creating small pieces of logic to mix and match as you like.

✅ Reusability
✅ Stateful logic
✅ Composition

Main takeaways

  1.  Now we can extract and reuse Vue's reactivity outside components for the first time.

  2. Every piece of code using reactivity now can be extracted and reused as a composable.

Final question 🥁

How much of your component's logic really belongs to the component?.

Recommendations

Don't go crazy

Don't try to reinvent the wheel:

Vue Use library

Thank you 🙏

Reactivity Vue 3

By Juan Andrés Núñez

Reactivity Vue 3

  • 412