Vue watchEffect vs watch

User
Vue watcheffect vs watch
Assistant
In Vue 3, both `watchEffect` and `watch` are **reactivity APIs**, but they serve different purposes and have different behaviors. Here's a clear comparison:

### `watchEffect`

– **Use Case**: Automatically tracks **all reactive dependencies** used inside its callback and re-runs when any of them change.
– **Usage**:

import { watchEffect } from 'vue';

  watchEffect(() => {
    console.log(myVar.value); // automatically tracks this
  });

– **Pros**:
– No need to manually specify dependencies.
– Great for simple side effects that depend on multiple reactive sources.

– **Cons**:
– Less control—can re-run more often than needed.
– Can be hard to debug if many dependencies are accessed inside.

### `watch`

– **Use Case**: Tracks a **specific** reactive source or sources.
– **Usage**:

import { watch } from 'vue';

  watch(myVar, (newVal, oldVal) => {
    console.log('Changed from', oldVal, 'to', newVal);
  });

– **Pros**:
– More control over what to watch.
– Provides access to old and new values.
– You can set options like `immediate`, `deep`, `flush`.

– **Cons**:
– You must explicitly declare dependencies.

### Summary Table:

| Feature | `watchEffect` | `watch` |
|—————–|—————————————-|——————————————|
| Dependency tracking | Automatic | Manual |
| Access to old value | No | Yes |
| Fine-grained control | Less | More |
| Suitable for | Quick side-effects | Watching specific value changes |
| Lazy execution | No (runs immediately) | Yes (can be lazy unless `immediate: true`) |

### When to use what?

– Use **`watchEffect`** when you just need to react to reactive state changes without caring which one changed.
– Use **`watch`** when you want precise control, like comparing old and new values, or deep-watching an object.

Let me know if you want real-life examples too.

User
Git api display commit message in both watch and watcheffect
Assistant
To display Git commit messages using an API in both `watch` and `watchEffect`, here's a Vue 3 example using a simple reactive variable (e.g., `repoName`) and fetching data when it changes.

### Setup:
We simulate fetching commits from GitHub API when `repoName` changes.

<script setup>
import { ref, watch, watchEffect } from 'vue';
import axios from 'axios';

const repoName = ref('vuejs/core'); // format: owner/repo
const commits = ref([]);
const isLoading = ref(false);

// Using watch
watch(repoName, async (newRepo) => {
  isLoading.value = true;
  try {
    const res = await axios.get(`https://api.github.com/repos/${newRepo}/commits`);
    commits.value = res.data.map(c => c.commit.message);
  } catch (error) {
    commits.value = ['Error fetching commits'];
  } finally {
    isLoading.value = false;
  }
});

// Using watchEffect (for demo: also fetch on initial load)
watchEffect(async () => {
  if (!repoName.value) return;
  isLoading.value = true;
  try {
    const res = await axios.get(`https://api.github.com/repos/${repoName.value}/commits`);
    commits.value = res.data.map(c => c.commit.message);
  } catch (error) {
    commits.value = ['Error fetching commits'];
  } finally {
    isLoading.value = false;
  }
});
</script>

<template>
  <div>
    <input v-model="repoName" placeholder="Enter repo (e.g., vuejs/core)" />
    <p v-if="isLoading">Loading...</p>
    <ul v-else>
      <li v-for="(msg, index) in commits" :key="index">{{ msg }}</li>
    </ul>
  </div>
</template>

### Notes:

– The **`watch`** is triggered when `repoName` changes.
– The **`watchEffect`** runs immediately and again whenever `repoName` changes (so yes, in this case it duplicates the call unless you remove one).
– In real apps, you'd choose one depending on need—`watch` for old vs new comparison, `watchEffect` for quick reactive side effects.

Want a version using just one (e.g., only `watch`) or more optimized with debounce?

User
Mounted vs watcheffect
Assistant
Great comparison question: `mounted()` vs `watchEffect()` in Vue 3. Here's a breakdown of how they differ and when to use each:

### `mounted()`

– **What it is**: A **lifecycle hook**.
– **When it runs**: Once **after the component is mounted** to the DOM.
– **Use case**: Ideal for running code that interacts with the DOM or needs to run once, like API calls on initial load.

**Example:**

<script setup>
import { onMounted } from 'vue';

onMounted(() => {
  console.log('Component mounted!');
  fetchData();
});
</script>

### `watchEffect()`

– **What it is**: A **reactivity tracking function**.
– **When it runs**: Immediately on setup, and **re-runs** whenever any reactive dependency used inside it changes.
– **Use case**: Useful for tracking reactive state and running side effects **automatically** based on those changes.

**Example:**

<script setup>
import { ref, watchEffect } from 'vue';

const count = ref(0);

watchEffect(() => {
  console.log('Count is:', count.value); // runs once and again every time count changes
});
</script>

### Summary Table

| Feature | `mounted()` | `watchEffect()` |
|———————–|————————————|——————————————|
| Type | Lifecycle Hook | Reactive Side Effect |
| Runs when | Once after DOM is mounted | Immediately, then on any dependency change |
| Reactivity awareness | No | Yes |
| Typical use cases | Fetch data, set up DOM, plugins | React to reactive state automatically |
| Runs more than once? | No | Yes |

### When to Use:

– Use **`mounted()`** when you want to do something **once**, like:
– Fetching initial data
– Starting a library
– Accessing `$refs`

– Use **`watchEffect()`** when you want to **automatically react to reactive changes**, like:
– Watching `route` changes
– Updating something when a `ref` or `computed` changes

Let me know if you want an example comparing both in the same component.

User
Example of mounted and why this will use
Assistant
Here's a practical example showing **`mounted()`** in action, along with **why you'd use it**:

### Example: Fetch GitHub Repo Info on Mount

<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'

const repoName = ref('vuejs/vue')
const repoInfo = ref(null)
const isLoading = ref(true)
const error = ref('')

onMounted(async () => {
  try {
    const response = await axios.get(`https://api.github.com/repos/${repoName.value}`)
    repoInfo.value = response.data
  } catch (err) {
    error.value = 'Failed to fetch repo info.'
  } finally {
    isLoading.value = false
  }
})
</script>

<template>
  <div>
    <h2>GitHub Repo Info</h2>
    <p v-if="isLoading">Loading...</p>
    <p v-if="error">{{ error }}</p>
    <div v-if="repoInfo">
      <p><strong>Name:</strong> {{ repoInfo.name }}</p>
      <p><strong>Stars:</strong> {{ repoInfo.stargazers_count }}</p>
      <p><strong>Description:</strong> {{ repoInfo.description }}</p>
    </div>
  </div>
</template>

### Why Use `onMounted` Here?

– **Runs once**: You only want to fetch the data **once**, when the component is loaded.
– **Avoid repeated calls**: You don’t want it to rerun on reactive changes like `repoName` unless you explicitly choose to.
– **DOM ready**: Useful if the logic depends on something being in the DOM (e.g., `$refs`, third-party libraries, or layout calculations).

### When *not* to use `onMounted`:
– When you want something to reactively update based on `ref` or `prop` changes (for that, use `watch` or `watchEffect`).

Let me know if you want a comparison with `watchEffect` for this use case!

Leave a Comment

Your email address will not be published. Required fields are marked *