title: vue2 composition api beforeRouteUpdate updating after the route changes
body: <p>I have this route:</p>
  <pre><code>{
    path: &quot;/categories/:categorySlug&quot;,
    name: &quot;product-list&quot;,
    meta: {
      title: &quot;Categories&quot;,
    },
  },
  </code></pre>
  <p>When the component first loads, it pulls in the category and any products related to it. The problem is when I change the category slug, for some reason the category updates fine, but the products do not.
  I decided to add a <strong>beforeRouteUpdate</strong> to force the products to change and I set it up like this:</p>
  <pre><code>export default defineComponent({
    name: &quot;ProductList&quot;,
    components: { Brands, Chooser, Products },
    setup() {
      const instance = getCurrentInstance();
      const searchTerm = computed(() =&gt; {
        return instance.proxy.$route.params.searchTerm;
      });
  
      const {
        brands,
        brandError,
        brandFacets,
        brandsLoading,
        brandsHasMoreResults,
        brandsItemsToShow,
        brandsQuery,
        brandsTotal,
        brandsFetchMore,
      } = useSearchBrands(searchTerm, 12, [], true);
      const {
        category,
        categoryError,
        categoryLoading,
        products,
        productError,
        productFacets,
        productsLoading,
        productsHasMoreResults,
        productsItemsToShow,
        productsQuery,
        productsTotal,
        productsFetchMore,
      } = useListProducts(instance);
  
      return {
        brands,
        brandError,
        brandFacets,
        brandsLoading,
        brandsHasMoreResults,
        brandsItemsToShow,
        brandsQuery,
        brandsTotal,
        category,
        categoryError,
        categoryLoading,
        products,
        productError,
        productFacets,
        productsLoading,
        productsHasMoreResults,
        productsItemsToShow,
        productsQuery,
        productsTotal,
        brandsFetchMore,
        productsFetchMore,
      };
    },
    beforeRouteUpdate(to, from, next) {
      console.log(to);
      this.productsQuery.refetch();
      next();
    },
  });
  </code></pre>
  <p>At first glance it didn't look like anything happened, because if I changed route it still showed the same products as the first load. But if I change again, I noticed that it now displayed the products from the previous route change:</p>
  <p><a href="https://i.stack.imgur.com/4aTwV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/4aTwV.png" alt="enter image description here" /></a></p>
  <p>And if I change route from <strong>ovens</strong> to <strong>coffee-machines</strong> it will show the ovens.
  I cant use <strong>beforeRouteEnter</strong> because I don't have access to <strong>this</strong> and using <strong>beforeRouteLeave</strong> doesn't update the component at all, even though in my logs, I can see the request is changing.</p>
  <p>So, to summarise, when I change route using <strong>beforeRouteUpdate</strong> I can see in my logs that the request changes to the correct category and I can see the correct products returned, but I don't see the results in the component until I change route again (with the same component).</p>
  <p>Does anyone know how I can fix this?</p>
  <hr />
  <p><strong>Update</strong>
  I have been asked to display the code for my product list. I use vue apollo and I have two generic functions, the first is <strong>useGraphQuery</strong> which looks like this:</p>
  <pre><code>import { ref } from &quot;vue-demi&quot;;
  
  import { useQuery, useResult } from &quot;@vue/apollo-composable&quot;;
  
  export function useGraphQuery(params, gql, pathFn, clientId = &quot;apiClient&quot;) {
    if (!params?.value)
      return {
        response: ref(undefined),
        loading: ref(false),
        error: ref(undefined),
        query: ref(undefined),
      };
  
    // TODO: figure our a way to skip the call if the parameters are null
  
    const { result, loading, error, query, fetchMore } = useQuery(gql, params, {
      clientId,
      //enabled: !!params?.value,
    });
    const response = useResult(result, null, pathFn);
  
    return { response, loading, error, query, fetchMore };
  }
  </code></pre>
  <p>All my graphql queries use this.
  Then for searches (i.e. the product search), uses another function called <strong>useGraphSearch</strong>:</p>
  <pre><code>import { computed } from &quot;@vue/composition-api&quot;;
  
  import { useGraphQuery } from &quot;./graph-query&quot;;
  
  export function useGraphSearch(params, gql, pathFn) {
    const { response, loading, error, query, fetchMore } = useGraphQuery(
      params,
      gql,
      pathFn
    );
  
    const items = computed(() =&gt; {
      if (!response.value) return [];
      return response.value.items;
    });
  
    const facets = computed(() =&gt; {
      if (!response.value) return [];
      return response.value.facets;
    });
  
    const total = computed(() =&gt; {
      if (!response.value) return 0;
      return response.value.total;
    });
  
    const hasMoreResults = computed(() =&gt; {
      if (!response.value) return false;
      return response.value.hasMoreResults;
    });
  
    const itemsToShow = computed(() =&gt; params.value.search.itemsToShow);
  
    const more = () =&gt; {
      useGetMore(params.value, fetchMore);
    };
  
    return {
      error,
      facets,
      hasMoreResults,
      items,
      itemsToShow,
      loading,
      query,
      total,
      more,
    };
  }
  
  function useGetMore(params, fetchMore) {
    params.search.page++;
  
    fetchMore({
      variables: params,
    });
  }
  </code></pre>
  <p>On the route I mentioned before, there are 3 queries running. One of them seems to work without doing anything. that is the <strong>useGetCategory</strong> which looks like this:</p>
  <pre><code>import { computed } from &quot;@vue/composition-api&quot;;
  
  import * as getCategoryBySlug from &quot;@graphql/api/query.category.gql&quot;;
  
  import { useGraphQuery } from &quot;./graph-query&quot;;
  
  export function useGetCategory(instance) {
    const params = computed(() =&gt; {
      const route = instance.proxy.$route;
      const slug = route.params.categorySlug;
      if (!slug) return;
      return { slug };
    });
  
    const { response, error, loading } = useGraphQuery(
      params,
      getCategoryBySlug,
      (data) =&gt; data.categoryBySlug
    );
  
    return { category: response, categoryError: error, categoryLoading: loading };
  }
  </code></pre>
  <p>This updates regardless whether I called <strong>beforeRouteUpdate</strong> or not.
  The second one is the <strong>useListProducts</strong> which looks like this:</p>
  <pre><code>import { ComponentInternalInstance } from &quot;@vue/composition-api&quot;;
  
  import { useSearchCategoryProducts } from &quot;@logic/search-products&quot;;
  import { useTrackProductImpressions } from &quot;@logic/track-product-impressions&quot;;
  import { useTrackProductClick } from &quot;@/_shared/logic/track-product-click&quot;;
  
  export function useListProducts(instance: ComponentInternalInstance) {
    const {
      products,
      productError,
      productFacets,
      productsLoading,
      productsHasMoreResults,
      productsItemsToShow,
      productsQuery,
      productsTotal,
      productsFetchMore,
    } = useSearchCategoryProducts(instance);
  
    return {
      products,
      productError,
      productFacets,
      productsLoading,
      productsHasMoreResults,
      productsItemsToShow,
      productsQuery,
      productsTotal,
      productsFetchMore,
    };
  }
  </code></pre>
  <p>as you can see here, this calls <strong>useSearchCategoryProducts</strong> which is just used to create the parameters and looks like this:</p>
  <pre><code>export function useSearchCategoryProducts(
    instance: ComponentInternalInstance,
    orderBy = [{ key: &quot;InVenue&quot;, value: &quot;desc&quot; }]
  ) {
    const params = computed(() =&gt; {
      const slug = instance.proxy.$route.params.categorySlug;
      if (!slug) return;
      const filters = createFilters(&quot;CategorySlug&quot;, [slug]);
      const request = createRequest(defaultParameters, 1, filters, orderBy);
      return { search: request };
    });
  
    return queryProducts(params);
  }
  
  function queryProducts(params) {
    console.log(params);
    const {
      error,
      facets,
      hasMoreResults,
      items,
      itemsToShow,
      loading,
      query,
      total,
      more,
    } = useGraphSearch(params, searchProducts, (data) =&gt; data.searchProducts);
    return {
      products: items,
      productError: error,
      productsLoading: loading,
      productFacets: facets,
      productsHasMoreResults: hasMoreResults,
      productsItemsToShow: itemsToShow,
      productsTotal: total,
      productsQuery: query,
      productsFetchMore: more,
    };
  }
  </code></pre>
  <p>You can see the <strong>console.log</strong> in the private function <strong>queryProducts</strong> which I can see that the params are updating.
  I know this is a lot to take in, but I have created the <strong>useGraphQuery</strong> and <strong>useGraphSearch</strong> so I can ensure that every query I create is the same and should work in the same way. The reason <strong>useGetCategory</strong> and <strong>useListProducts</strong> don't work in the same way (i.e. the category changes when the route does, but the product list doesn't) is beyond me and it is the reason I am trying to implement <strong>beforeRouteUpdate</strong> at all.</p>
  <p>The code for the setup looks like this btw:</p>
  <pre><code>import {
    computed,
    defineComponent,
    getCurrentInstance,
  } from &quot;@vue/composition-api&quot;;
  
  import Brands from &quot;@components/brands/brands.component.vue&quot;;
  import Chooser from &quot;@components/chooser/chooser.component.vue&quot;;
  import Products from &quot;@components/products/products.component.vue&quot;;
  import { useListProducts } from &quot;./list-products&quot;;
  import { useSearchBrands } from &quot;@logic/search-brands&quot;;
  import { useGetCategory } from &quot;@logic/get-category&quot;;
  
  export default defineComponent({
    name: &quot;ProductList&quot;,
    components: { Brands, Chooser, Products },
    setup() {
      const instance = getCurrentInstance();
      const searchTerm = computed(() =&gt; {
        return instance.proxy.$route.params.categorySlug;
      });
  
      const { category, categoryError, categoryLoading } =
        useGetCategory(instance);
  
      const {
        brands,
        brandError,
        brandFacets,
        brandsLoading,
        brandsHasMoreResults,
        brandsItemsToShow,
        brandsQuery,
        brandsTotal,
        brandsFetchMore,
      } = useSearchBrands(searchTerm, 12, [], true);
      const {
        products,
        productError,
        productFacets,
        productsLoading,
        productsHasMoreResults,
        productsItemsToShow,
        productsQuery,
        productsTotal,
        productsFetchMore,
      } = useListProducts(instance);
  
      return {
        brands,
        brandError,
        brandFacets,
        brandsLoading,
        brandsHasMoreResults,
        brandsItemsToShow,
        brandsQuery,
        brandsTotal,
        category,
        categoryError,
        categoryLoading,
        products,
        productError,
        productFacets,
        productsLoading,
        productsHasMoreResults,
        productsItemsToShow,
        productsQuery,
        productsTotal,
        brandsFetchMore,
        productsFetchMore,
      };
    },
    beforeRouteUpdate(to, from, next) {
      console.log(to);
      this.brandsQuery.refetch();
      this.productsQuery.refetch();
      next();
    },
  });
  </code></pre>