Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop when using the render function and the ref parameter. #4743

Closed
3 tasks done
schoonc opened this issue Mar 21, 2022 · 3 comments · Fixed by #6014
Closed
3 tasks done

Infinite loop when using the render function and the ref parameter. #4743

schoonc opened this issue Mar 21, 2022 · 3 comments · Fixed by #6014
Labels
Meta: Help Wanted Package: vue Issues related to the Sentry Vue SDK Type: Bug

Comments

@schoonc
Copy link

schoonc commented Mar 21, 2022

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which package are you using?

@sentry/vue

SDK Version

6.18.2

Framework Version

3.2.31

Link to Sentry event

No response

Steps to Reproduce

main.js:

import { createApp, h, ref} from 'vue'
import MyComp from './MyComp.vue'
import * as Sentry from '@sentry/vue'

const myComp = ref()
const app = createApp({
    render() {
        return h(MyComp, { ref: myComp})
    }
})
Sentry.init({
    app,
    dsn: 'some-dsn', // Here you must insert the real "dsn" so that "sentry" will initialize.
    environment: 'some-env',
})
app.mount('#app')

MyComp.vue:

<template>
  <div
    :data-test="test"
  />
</template>

<script>

export default {
  created() {
    /* "setTimeout" and "$forceUpdate" are not related to the problem. It's just a way to cause a component 
        to redraw after a certain amount of time has passed since it was created. */
    setTimeout(() => {
      this.$forceUpdate()
    }, 3000)
  }
}
</script>

After redrawing the component ($forceUpdate), we get the result described below in the actual result section.

The problem disappears if:

  • Do not pass the ref param, like return h(MyComp) instead of return h(MyComp, { ref: myComp})
  • Use SFC (single file component) instead the render function, like const app = createApp(App), App.vue:
<template>
    <my-comp ref="myComp" />
</template>

<script>
import { ref } from 'vue'
import MyComp from './MyComp.vue'
export default {
    components: {
        MyComp
    },
    setup() {
        const myComp = ref()
        return {
            myComp
        }
    }
}
</script>

Expected Result

The application continues to work normally and the console shows this

image

Actual Result

The application goes into an infinite loop, and the console starts to be continually bombarded with this:

image

@AbhiPrasad
Copy link
Member

Hey thanks for writing in. I was able to replicate this (https://stackblitz.com/edit/vue-g6usgy?file=src/main.js). I'm not sure why this is happening, not familiar enough with Vue internals to know what's going on with the render function. Any ideas why there is a difference here?

Perhaps we can improve

export const attachErrorHandler = (app: Vue, options: Options): void => {
somehow?

Backlogging, but help is appreciated!

@szykub
Copy link

szykub commented May 19, 2022

@AbhiPrasad Hey, any update on that? Got a problem with it also.

@schoonc
Copy link
Author

schoonc commented May 19, 2022

I don't know, but it's possible to pass an externally created ref into an application is a forbidden technique. And that's exactly what I was doing:
image

It's probably better to emit an event from a component and pass in the event arguments the necessary data. In my case, I actually needed a root element. So I ended up doing something like this:

main.js:

import { createApp, h} from 'vue'
import MyComp from './MyComp.vue'

let myCompRootEl = null
const app = createApp({
    render() {
        return h(MyComp, { 
          onMounted: (rootEl) => {
            myCompRootEl = rootEl
          }
        })
    }
})
app.mount('#app')

MyComp.vue:

<template>
  <div
    ref="rootEl"
  />
</template>

<script>

export default {
  mounted() {
    this.$emit('mounted', this.$refs.rootEl)
  }
}
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Meta: Help Wanted Package: vue Issues related to the Sentry Vue SDK Type: Bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants