Setup function in Composition API – Vue 3

Setup function in Composition API – Vue 3

Setup Function in Composition API - VUE 3

In Vue.js 2, Component objects could have data, computed, methods, and watch options. We will be using these options to write component functional logics. But when our component grows bigger, the functional logic also grows. So we end up to write the same logic in different options. Meaning that, we have to write some parts in the data options, some parts in the methods and others(computed, watch) also. So it will be difficult to understand the component core logics, Since it has been written in different places.

Finally, Vue.js 3 introduced a Composition API where we can solve such problems. In Composition API, we can write or composite all options logics(data, computed, methods, watch) in a single place.

In Composition API, we call this place the setup. We can composite or write all component core logics in the setup function. Here we can organize single core logics even for the complex components. It will be very helpful to read about Single File Components in Vue 3 before moving to setup functions in this session. Let’s take the deep dive!

Setup function in Composition API

setup function is the entry point in the Composition API. It will be called before the component is created and after the props are prepared. Meaning that, before compiling and processing it’s template into a render object. Setup function is called before the beforeCreate hook. Note that this reference won’t be available inside the setup function. Because the component is not created yet.

Next we are going to see how to use the setup function. The setup is the function with two arguments(props and context). Anything returned from the setup function will be available throughout our component. In Addition to that It will be accessible inside the template also. Let me explain the same with the below example.

Setup Function syntax with example

CustomButton.vue

<template>
  <div>
    <button>
      {{ label }}
    </button>
  </div>
</template>

<script>
export default {
  props: {
    label: String,
  },
  setup(props) {
    console.log(props); // { label: '' }
    
    // Write Component Core Logics here
    
    // Anything returned from setup function will be
    // available throughout our component
    return {};
  },
  // return object from setup function accessible here
};
</script>

Setup function in Composition API – Arguments

Setup function has two arguments,

  1. props
  2. context

Let’s see how these arguments are being used in the components.

Props

Props is the first argument of setup function, which are reactive by nature. So while we update the props, the component will be updated. The basic example as follows,

export default {
  props: {
    label: String,
  },
  setup(props) {
    console.log(props.label);

  },
  
};

Props with ES6 Destructive

Note that props are reactive by default. So we can not use Object destructuring since it will remove reactive property. We can solve such problems using toRefs. toRefs is useful when the reactive objects are being destructure/spread.

import { toRefs } from "vue";
export default {
  props: {
    label: String,
  },
  setup(props) {
    const { label } = toRefs(props);
    console.log(label.value);
  },
};

Note that, if label is an optional prop, then toRefs will not create a reactive reference for the label. Here we are in need to use toRef instead of toRefs. Let me show the same with below example,

import { toRef } from "vue";
export default {
  props: {
    label: String,
  },
  setup(props) {
    const label = toRef(props, "label");
    console.log(label.value);
  },
};

Context

Context is the second argument of the setup function which is not reactive by nature. This is the normal JavaScript object. It has three component properties,

  1. attrs – Attributes (Non-Reactive)
  2. slots – Slots (Non-Reactive)
  3. emit – Method (Emit events)
export default {
  setup(props, context) {
    console.log(context.attrs) // (Non-reactive)

    console.log(context.slots) // (Non-reactive)

    console.log(context.emit) // Emit Events
  }
}

Note that context is not reactive. So we can use Object destructuring here as follows,

export default {
  setup(props, { attrs, slots, emit }) {
    // write logics here
  }
}

Setup function with Template

Properties of props and anything returned from the setup function will be accessible in the component’s template. Let me explain with the below example,

CustomButton.vue

<template>
  <div>
    <div>{{ counterMsg.msg }} : {{ counter }}</div>
    <button @click="() => counter++">
      {{ label }}
    </button>
  </div>
</template>

<script>
import { ref, reactive } from "vue";
export default {
  // props properties accessible to template
  props: {
    label: String,
  },
  setup(props) {
    console.log(props.label);
    const counter = ref(0);
    const counterMsg = reactive({ msg: "Click the Button" });
    // below object accessible to template
    return {
      counter,
      counterMsg,
    };
  },
};
</script>

In the above example counter, counterMsg are from setup function and label from props which are accessible in the template. Note that when we access the ref inside template, it will unwrap the inner value automatically. No need to append .value in the template. For more details you can refer Ref vs Reactive in Vue 3

Setup function with render { h }

As same as with template, we can use setup with render functions also. Here we will be using h instead of template in the component. Let me explain with below example,

CustomButton.vue

<script>
import { ref, reactive, h } from "vue";
export default {
  // props properties accessible to template
  props: {
    label: String,
  },
  setup(props) {
    console.log(props.label);
    const counter = ref(0);
    const counterMsg = reactive({ msg: "Click the Button" });
    // Note that we have to give ref value in in render function
    return () =>
      h(
        "div",
        null,
        counterMsg.msg + ":" + counter.value,
        h(
          "button",
          {
            onClick: () => counter.value++,
          },
          props.label
        )
      );
  },
};
</script>

In the above example, the same component has been implemented using the render function. We can convert our template into render function (h) using Template Compilation

Conclusion

So we have learned about setup functions today. Composition API is the fundamental concept of Vue3. The ultimate goal of composition API is to organize the complex component logics in the single place. Typically the place is nothing but the setup function. Another important point is this won’t be available here unlike other options in the component.

Leave a Reply

%d bloggers like this: