0

When I changed something in a Vue nested component and saved it. The Vite HMR will constantly reload the component. And then it caused a warning of vue: Maximum recursive updates exceeded...

Try online Demo on stackblitz. Change something in Child1.vue and save. You can see 101 times same info and a warning in console.

Or code blow with Vue3.x + Vite4.x/5.x:

Child1.vue

<script setup lang="ts">
const emits = defineEmits(['list-change']);

emits('list-change', ['a', 'b', 'c']);

// change something and save
console.log('Child1.vue setup');
</script>

Child2.vue

<script setup lang="ts">
const props = defineProps<{
  list: string[];
}>();
</script>

App.vue

<template>
  <Child1 @list-change="handleListChange"></Child1>
  <Child2 :list="list"></Child2>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import Child1 from './components/Child1.vue';
import Child2 from './components/Child2.vue';

const list = ref<string[]>([]);
const handleListChange = (newList: string[]) => {
  list.value = newList;
};

console.log('App.vue setup');
</script>

Thanks for help.

3
  • This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself - the warning tells you what you're doing wrong, if you read the WHOLE warning Commented Dec 12, 2023 at 5:01
  • @JaromandaX yes of course I read the warning but there's no such mutatings in the three components. Commented Dec 12, 2023 at 5:14
  • yeah, I see ... something odd about doing the emit in the setup though - if you wrap it in a setTimeout then the issue goes away Commented Dec 12, 2023 at 5:18

1 Answer 1

1

the problem here is you are calling emits('list-change', ['a', 'b', 'c', 'k', 'o']); directly on child load , what is happening here is that first app loads that registers function for list-change event then child1 loads and emits that event , now app will listen event and updates list and re-renders whole app cus child2 is using that list , that will again load child1 (cuz of re-render) and again event will be emmited , this loop goes on and on till stack is full.

to prevent this keep emits call in function and call that function in button click

Child1

<script setup lang="ts">
const emits = defineEmits(['list-change']);
function test() {
  console.log('Updating List');
  emits('list-change', ['a', 'b', 'c', 'k', 'o']);
}

// change something and save
console.log('Child1.vue setup');
</script>
<template>
  <button @click="test">TEST 2</button>
</template>

or use onMount

<script setup lang="ts">
import {onMount} from 'vue';
const emits = defineEmits(['list-change']);

onMount(() => {
emits('list-change', ['a', 'b', 'c', 'k', 'o']);
});


// change something and save
console.log('Child1.vue setup');
</script>
Sign up to request clarification or add additional context in comments.

5 Comments

or just in a setTimeout
Yup @JaromandaX anything that takes emit outside of initialization flow , event timeout od 0s will also work :)
Thanks for your answers. But I'm confused why "...re-renders whole app cus child2 is using that list...". And this problem will only be casued while developing with vite, not in production after build. If the rerender is due to the prop bind in Child2.vue, the problem will exist in production. So I'm confused. And Is there any way to solve it if the emit just needs to be done in setup, such as something need to be inited locally when component create.
You need to understand vue lifecycle for this vuejs.org/guide/essentials/lifecycle#lifecycle-diagram you can use onMounted hook to prevent this ``` <script setup> import {onMounted} from 'vue'; onMounted(() => emits('list-update', [1,2,3,4])) </script> ```
@DarshanPatel After long time trying to understand the process before mount, I almost get it~XD... I simply assume that changes of reactive data before mounting will make component rerender/reload and then trigger setup hook again and again... Thanks a lot for your advice and patience :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.