Subscribe on changes!

SSR watchEffect onInvalidate issue (Cannot access 'runner' before initialization)

avatar
tjk
Feb 27th 2021

See README in https://github.com/tjk/watcheffect-runner-bug

Version

3.0.6

Reproduction link

https://github.com/tjk/watcheffect-runner-bug

Steps to reproduce

git clone https://github.com/tjk/watcheffect-runner-bug
cd watcheffect-runner-bug
yarn
yarn dev

Then hit http://localhost:3000

What is expected?

No error

What is actually happening?

Error

avatar
Feb 27th 2021

During SSR, we return from doWatch before runner is initalized, but onInvalidate still references it, which throws this error.

Think we need to initialize it eagerly with let runner and also check for it to be set during onInvalidate execution before accessing runner.options.

But i have no idea how to write a test for this ...

avatar
tjk
Feb 27th 2021

I have no idea what I'm doing but I think this test is working --

// XXX find a way to not double setup and just generally not do this so hackily
it('effect onInvalidate succeeds in ssr context', (done) => {
  let instance: ComponentInternalInstance | null
  const noop = () => {}
  const Comp = defineComponent({
    setup() {
      if (!instance) {
        instance = getCurrentInstance()
      } else {
        watchEffect((onInvalidate) => {
          expect(() => onInvalidate(noop)).toThrow(ReferenceError)
          done()
        })
      }
    },
    render: noop,
  })
  createApp(Comp).mount(nodeOps.createElement('div'))
  setupComponent(instance!, true /* isSSR */)
})
avatar
tjk
Feb 27th 2021

Started a PR https://github.com/vuejs/vue-next/pull/3323 for someone who understands better to fix up. Thanks for the guidance @LinusBorg.