Bläddra i källkod

fix(ssr): watchEffect onInvalidate runner initialization (#3323)

close #3322
TJ Koblentz 5 år sedan
förälder
incheckning
e4b5fccd0c

+ 3 - 1
packages/runtime-core/src/apiWatch.ts

@@ -223,7 +223,7 @@ function doWatch(
   }
 
   let cleanup: () => void
-  const onInvalidate: InvalidateCbRegistrator = (fn: () => void) => {
+  let onInvalidate: InvalidateCbRegistrator = (fn: () => void) => {
     cleanup = runner.options.onStop = () => {
       callWithErrorHandling(fn, instance, ErrorCodes.WATCH_CLEANUP)
     }
@@ -232,6 +232,8 @@ function doWatch(
   // in SSR there is no need to setup an actual effect, and it should be noop
   // unless it's eager
   if (__NODE_JS__ && isInSSRComponentSetup) {
+    // we will also not call the invalidate callback (+ runner is not set up)
+    onInvalidate = NOOP
     if (!cb) {
       getter()
     } else if (immediate) {

+ 13 - 2
packages/server-renderer/__tests__/render.spec.ts

@@ -8,9 +8,10 @@ import {
   defineComponent,
   createTextVNode,
   createStaticVNode,
-  KeepAlive,
   withCtx,
-  Transition
+  KeepAlive,
+  Transition,
+  watchEffect
 } from 'vue'
 import { escapeHtml } from '@vue/shared'
 import { renderToString } from '../src/renderToString'
@@ -775,5 +776,15 @@ function testRender(type: string, render: typeof renderToString) {
       const html = await render(app)
       expect(html).toBe(`<div>hello</div>`)
     })
+
+    // https://github.com/vuejs/vue-next/issues/3322
+    test('effect onInvalidate does not error', async () => {
+      const noop = () => {}
+      const app = createApp({
+        setup: () => watchEffect(onInvalidate => onInvalidate(noop)),
+        render: noop,
+      })
+      expect(await render(app)).toBe('<!---->')
+    })
   })
 }