`router.push()` during setup leads to "Unhandled error during execution of scheduler flush." and then `node is null`
Vue version
3.2.36
Link to minimal reproduction
https://codesandbox.io/s/vue-router-push-setup-node-is-null-gwfl0f
Steps to reproduce
As soon as you open the reproduction you should be able to see the issue:
What is expected?
I would expect the redirect to happen without any issue.
What is actually happening?
There is currently an issue:
node is null
That is emitted after the following warning:
Unhandled error during execution of scheduler flush. This is likely a Vue internals bug.
System Info
No response
Any additional comments?
Context on discovery
I ran into this bug after implementing a "login by token", once the user would log in the app it would be redirected to the page he was requesting. Doing this like the above leads to the issue. In order to avoid an async setup
I changed my code to something like:
<script setup>
import { useRouter } from "vue-router";
const router = useRouter();
- await router.push({ path: "/about" });
+ Promise.resolve().then(() => { router.push({ path: "/about" }); });
</script>
What seems to happen
It looks like:
- VueJs is waiting to render the component
- The router redirect to another route
- VueJs renders the new route
- VueJs tries to compute the diff with the old view state, here it fails as this view has never been rendered
Correct approach
I am unsure that my approach is the correct one, in fact I declare a view that will never be rendered, there may be other approach that are more correct in this context.
maybe you should use isReady instead.
router.isReady().then(onSuccess).catch(onError)
see https://router.vuejs.org/guide/migration/#replaced-onready-with-isready
I did not knew about the isReady
method. I did not try with this, instead I went to use a beforeEnter
navigation guard with an empty component:
const routes = [
{
path: '/login/:token',
name: 'login-token',
beforeEnter: async (_to, _from, next) => {
await Promise.resolve(true); // Here I am doing calls to my API.
next({ path: '/about' });
},
component: () => '',
},
];