Search code examples
javascriptregexvue.jsvuejs3

"if regex.test" doesn't works properly on javascript vuejs router


const router = createRouter({
  history: createWebHistory(),
  routes,
});

// ...

const allowedToAnonymous = [
  /^\/login$/g,
  /^\/signup$/g,
  /^\/home$/g,
  /^\/emailconfirm\/[0-9a-zA-Z]{8}$/g,
  /^\/serviceGuide$/g,
  /^\/$/g
];

router.beforeEach((to, from) => {
  for (var regex of allowedToAnonymous) {
    console.log(regex);
    console.log(to.path);
    if (regex.test(to.path)) {
      console.log('return');
      return;
    } else {
      console.log(regex.test(to.path));
      console.log('do not return');
    }
  }

  const checkLogin = stores.getters['userStore/checkLogin'];
  if (!checkLogin) return '/login';
});

I wrote the above code in my vuejs project. It redirects to the login page if the specific regular expressions and the current path do not match and you are not logged in. All console.log functions are for debugging. If I test this in web browser, it results like below:

/^\/login$/g
/serviceGuide
false
do not return
/^\/signup$/g
/serviceGuide
false
do not return
/^\/home$/g
/serviceGuide
false
do not return
/^\/emailconfirm\/[0-9a-zA-Z]{8}$/g
/serviceGuide
false
do not return
/^\/serviceGuide$/g
/serviceGuide
true
do not return
/^\/$/g
/serviceGuide
false
do not return
/^\/login$/g
/login
return

Look near the /^\/serviceGuide$/g output. Even though the result of regex.test is true, it seems that it is proceeding in a do not return branch. This does not happen all the time, and it does occur when I repeatedly browse the website 2~4 times.

Why does this happen and what is the solution?


Solution

  • If the regexes are being saved between multiple navigations, that could be the reason for the inconsistent behaviour. Take for instance the following code:

    let regex = /^\/serviceGuide$/g
    console.log(regex.test('/serviceGuide')); // true
    console.log(regex.test('/serviceGuide')); // false
    console.log(regex.test('/serviceGuide')); // true
    console.log(regex.test('/serviceGuide')); // false
    console.log(regex.test('/serviceGuide')); // true
    

    This is because of the /g flag that you put on your regex -- regex.test searches for subsequent matches after the first. If you remove it, you won't have this issue, and it will match from the beginning.

    The behaviour you are getting is because you're in a state where you enter the function after a succesful match. This means the first regex.test inside the function returns false, and then the second one returns true.

    TL;DR: Remove the /g flag.