Home > database >  Vue reactivity fails when navigating back to the page
Vue reactivity fails when navigating back to the page

Time:01-12

I use a simple binary Vue variable named binary_state to control the class of an element, named "controlled_element" in the rest of this question. "controlled_element" has two classes "class_true" and "class_fasle" as determined by the value of binary_state. The value of binary_state itself switches between true and false using a button on the page. Let's call that button "controlling_element".

Every time the value of binary_state changes using "controlling_element", the updated value is sent to the server. On the other hand, every time the page is refreshed, an updated value for binary_state is retrieved from the server. Once that happens, the class of the "controlled_element" gets adjusted too.

It is a pretty straightforward scenario. Now consider the following steps:

  1. Refresh the page, so a fresh value of binary_state gets retrieved from the server. For simplicity, let's assume the fresh value is true, i.e., binary_state=true. This will set the class of "controlled_element" to "class_true".
  2. Press the "controlling_element" an odd number of times. This will set binary_state and the class of "controlled_element" to "false" and "class_false", respectively.
  3. Navigate away from the page and come back to it using the back arrow (button) of the browser.
  4. I expect the value of binary_state to continue to be false. That seems to be actually the case, as seen on the Vue devtool plugin.
  5. I also expect the class of "controlled_element" to continue to be "class_false". However, to my surprise, the class is "class_true", which is the latest value received from the server regardless of all the changes that were applied in step 2.

Note that when navigating back to the page, the sync (reactivity) between binary_state and the class of "controlled_element" gets violated: As mentioned in step 4 above, the value of binary_state continues to be false (as indicated by the Vue devtool plugin), but the class of "controlled_element" is "class_true".

NOTE. I have seen this issue in chrome (Version 108.0.5359.125 (Official Build) (64-bit)) and Edge (108.0.1462.76 (Official build) (64-bit)), but everything is fine with Firefox (108.01.1 (64-bit)).

Three final remarks.

  • I have seen this related question. The author indicates they were able to solve the issue by setting autocomplete="on" of the form. I am not sure if that is helpful for me, because I do not have a form, to begin with.
  • I have seen some suggestions on using vuex or localStorage, but I am not sure if that is necessary in my case because, as mentioned in step 4, the Vue value binary_state seems to have the correct value.
  • I am not using vue-router if that has a bearing on this topic.

CodePudding user response:

Well, to be honest, I have some suggestions depending on which version of vue you are using. For example, if you are using Vue2 or Vue3 with the cli, your state management problems can be solved with Vuex (however at this point vuex is not the officially recommended state management system anymore). The best solution, if you're using Vue3, is to go with Pinia https://pinia.vuejs.org which is very helpful, modern, and surprisingly easier to learn and use, compared to Vuex.

https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage localStorage is an alternate solution, but the tradeoff is that you will have to write code to erase that localStorage.

https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage sessionStorage is similar to localStorage but will automatically erase the data after the window closes.

CodePudding user response:

I solved the issue by manually reloading the page when a user visits the page using the browser back/forward buttons. The following code snippet does it:

<script>
    if (performance) {
        // get the PerformanceNavigationTiming object
        const perfEntries = performance.getEntriesByType("navigation");
        const perfNavTiming = perfEntries && perfEntries[0];

        if (perfNavTiming) {
            // get the type of navigation
            const navType = perfNavTiming.type;

            // reload if it is back_forward or prerender.
            if ((navType === "back_forward") ||
                (navType === "prerender")) {
                window.location.reload();
            }
        }
    }

</script>

It is not the neatest solution, but I guess I should go for it, given my time limit. I guess some learning is required before I can use the suggested solutions using localStorage, sessionStorage, and Piani, as I am not sure how to use these techniques to re-initiate the Vue two-way binding.

  • Related