From 84e309b6f2937cbf8d960549c226ffb6109dff41 Mon Sep 17 00:00:00 2001 From: Thomas Fjordside <48123373+tfjordside@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:33:26 +0100 Subject: [PATCH] feat: clear Nuxt state on unmount --- .playground/app.vue | 54 ++++++--------------- .playground/pages/page1.vue | 51 ++++++++++++++++++++ .playground/pages/page2.vue | 80 +++++++++++++++++++++++++++++++ .playground/pages/page3.vue | 51 ++++++++++++++++++++ components/LimboSearch.vue | 17 ++++--- composables/useLimboSearch.js | 88 ++++++++++++++++++----------------- 6 files changed, 251 insertions(+), 90 deletions(-) create mode 100644 .playground/pages/page1.vue create mode 100644 .playground/pages/page2.vue create mode 100644 .playground/pages/page3.vue diff --git a/.playground/app.vue b/.playground/app.vue index 468da3f..4549ff1 100644 --- a/.playground/app.vue +++ b/.playground/app.vue @@ -1,42 +1,18 @@ - - + + diff --git a/.playground/pages/page1.vue b/.playground/pages/page1.vue new file mode 100644 index 0000000..fa2b82f --- /dev/null +++ b/.playground/pages/page1.vue @@ -0,0 +1,51 @@ + + + diff --git a/.playground/pages/page2.vue b/.playground/pages/page2.vue new file mode 100644 index 0000000..e1fe632 --- /dev/null +++ b/.playground/pages/page2.vue @@ -0,0 +1,80 @@ + + + diff --git a/.playground/pages/page3.vue b/.playground/pages/page3.vue new file mode 100644 index 0000000..fa2b82f --- /dev/null +++ b/.playground/pages/page3.vue @@ -0,0 +1,51 @@ + + + diff --git a/components/LimboSearch.vue b/components/LimboSearch.vue index cc01292..a8a0cb3 100644 --- a/components/LimboSearch.vue +++ b/components/LimboSearch.vue @@ -6,19 +6,19 @@ diff --git a/composables/useLimboSearch.js b/composables/useLimboSearch.js index f3b22d0..b68d06c 100644 --- a/composables/useLimboSearch.js +++ b/composables/useLimboSearch.js @@ -8,7 +8,7 @@ export const useLimboSearch = async (options = {}) => { Except the searchKey, which should not be replaced post initiation! */ const { - searchKey = '', + searchKey = "", // searchFilters, // config = {}, // extraParameters = {}, @@ -53,7 +53,7 @@ export const useLimboSearch = async (options = {}) => { const defaultLimit = 12; const defaultConfig = { - callMethod: 'GET', // { string } The method to use for the call + callMethod: "GET", // { string } The method to use for the call enableLiveSearch: false, // { boolean|array } Can be an array of particular parameters triggering a live search or simply true or false immediateSearch: { useUrlQuery: true, @@ -62,14 +62,14 @@ export const useLimboSearch = async (options = {}) => { clearRouterHashOnSearch: false, // { boolean|object } Whether to clear the hash on search. If an object is used, the property "includeInitialSearch" to also clear for the first search, else that will be left out limit: { initial: defaultLimit, value: defaultLimit }, // { number|object } If a numeric limit is set, it will be used for both values - grouped paginations should be set with their ids (fx. limit: { 1: { initial: 18, value: 12 }, 2: { initial: 15, value: 6 } }). enableGroupedSearch: false, // { boolean } Make use of grouped pagination (l1, o1, l2, o2, (ie. l{id}, o{id}) etc.) instead of simply "limit" and "offset". - groupParameter: 'groups', // { string } When needing to "fetch more / all" we need a parameter to filter that. + groupParameter: "groups", // { string } When needing to "fetch more / all" we need a parameter to filter that. updateUrlQueryOnSearch: true, // { boolean } Allow the page's url to reflect the search updateVueRouteOnSearch: false, // { boolean|object } Allow the vue router to reflect the search - may cause issues if the page is keyed based off the query. /* NOT FULLY DONE YET (DON'T CURRENTLY RE-SEARCH): If an object is used, set "pushHistory" to make each individual search part of the browser history. */ clearSearchDataOnError: true, // { boolean } When toggled to false, the data from the previous search will persist on error allowSearchFiltersMutation: false, // { boolean } Needs to be explicitly turned on! updateSearchFiltersOnBindingChange: true, // { boolean } Whether a change in the bound search filters should trigger a change in the internally used data - persistentParameters: ['contextId'], // { array } Parameters that should always be present in a search (empty or not) - hiddenParameters: ['siteId', 'contextId', 'pageId', 'cultureId'], // { array } Parameters that should not be shown in the url. + persistentParameters: ["contextId"], // { array } Parameters that should always be present in a search (empty or not) + hiddenParameters: ["siteId", "contextId", "pageId", "cultureId"], // { array } Parameters that should not be shown in the url. defaultParameterValues: {}, // { object } Default values for parameters - parameters will not be shown in the url if they have the same value as the default value searchDelay: 0, // { number } Delay in ms before the search is triggered @@ -85,6 +85,10 @@ export const useLimboSearch = async (options = {}) => { onInit: () => {}, // { function } Hook for when the search is initiated. The reactive Limbo search object is passed as the first argument. }; + onBeforeUnmount(() => { + clearNuxtState([`searchData${searchKey}`, `searchState${searchKey}`]); + }); + const defaultSearchData = { data: null, facets: null, @@ -93,7 +97,7 @@ export const useLimboSearch = async (options = {}) => { misc: null, error: null, }; - const reservedParameters = ['limit', 'offset', 'total']; + const reservedParameters = ["limit", "offset", "total"]; const lastRequestedUrl = ref(null); @@ -183,10 +187,10 @@ export const useLimboSearch = async (options = {}) => { } const pagination = { limit: 0, offset: 0 }; const { limit, offset } = internalPagination.value ?? {}; - if (typeof limit !== 'undefined') { + if (typeof limit !== "undefined") { pagination.limit = limit; } - if (typeof offset !== 'undefined') { + if (typeof offset !== "undefined") { pagination.offset = offset; } return pagination; @@ -235,7 +239,7 @@ export const useLimboSearch = async (options = {}) => { compConfig.value.enableGroupedSearch && typeof internalExtraParameters.value[ compConfig.value.groupParameter - ] !== 'undefined' + ] !== "undefined" ) { const parameters = { ...searchFilterParameters.value, @@ -422,7 +426,7 @@ export const useLimboSearch = async (options = {}) => { requestTimeout.value = null; lastRequestedUrl.value = `${endpointUrl.value}?${serializedParams}`; - if (compConfig.value.callMethod === 'POST') { + if (compConfig.value.callMethod === "POST") { lastRequestedUrl.value = endpointUrl.value; } state.value.isAppend = !!append; @@ -430,7 +434,7 @@ export const useLimboSearch = async (options = {}) => { const data = await $fetch(lastRequestedUrl.value, { method: compConfig.value.callMethod, body: - compConfig.value.callMethod === 'POST' + compConfig.value.callMethod === "POST" ? compConfig.value.searchBodyTransformerMethod(params) : null, onResponseError({ response }) { @@ -512,7 +516,7 @@ export const useLimboSearch = async (options = {}) => { searchData.value.pagination = {}; } response?.groups?.forEach((group) => { - if ('id' in group) { + if ("id" in group) { searchData.value.pagination[group.id] = { limit: group.limit || 0, offset: group.offset || 0, @@ -551,7 +555,7 @@ export const useLimboSearch = async (options = {}) => { } }; // Run on client or server - if (typeof window !== 'undefined' && delay > 0) { + if (typeof window !== "undefined" && delay > 0) { await new Promise((resolve) => { window.clearTimeout(requestTimeout.value); requestTimeout.value = window.setTimeout(resolve, delay); @@ -582,10 +586,10 @@ export const useLimboSearch = async (options = {}) => { value != compConfig.value.defaultParameterValues?.[key]) || isPersistent ) { - array.push(`${key}=${value ?? ''}`); + array.push(`${key}=${value ?? ""}`); } } - return array.join('&'); + return array.join("&"); } function resetPagination() { @@ -623,9 +627,9 @@ export const useLimboSearch = async (options = {}) => { const router = useRouter(); function setUrlQuery(query = getSerializedParams(), clearHash = false) { - const array = query.split('&').filter((item) => { - const key = item.split('=').shift(); - let value = item.split('=').pop(); + const array = query.split("&").filter((item) => { + const key = item.split("=").shift(); + let value = item.split("=").pop(); // TODO: implement urlFilterMapping if ( @@ -661,15 +665,15 @@ export const useLimboSearch = async (options = {}) => { if ( key in defaultParameterValues && - String(defaultParameterValues[key]) === (value ?? '') + String(defaultParameterValues[key]) === (value ?? "") ) { return false; } return !compConfig.value.hiddenParameters?.includes?.(key); }); const transformedArray = array.map((item) => { - const key = item.split('=').shift(); - let value = item.split('=').pop(); + const key = item.split("=").shift(); + let value = item.split("=").pop(); if (key in compConfig.value.urlFilterMapping) { const mappedKey = compConfig.value.urlFilterMapping[key]; if (value in mappedKey) { @@ -680,15 +684,15 @@ export const useLimboSearch = async (options = {}) => { }); const url = - [route.path, transformedArray.join('&')].filter(Boolean).join('?') + + [route.path, transformedArray.join("&")].filter(Boolean).join("?") + (clearHash - ? '' - : typeof window !== 'undefined' + ? "" + : typeof window !== "undefined" ? window.location.hash : route.hash); const oldUrl = - typeof window === 'undefined' + typeof window === "undefined" ? route.fullPath : [ window.location.pathname, @@ -696,10 +700,10 @@ export const useLimboSearch = async (options = {}) => { window.location.hash, ] .filter(Boolean) - .join(''); - typeof window !== 'undefined' && + .join(""); + typeof window !== "undefined" && compConfig.value.updateUrlQueryOnSearch && - window.history.replaceState(window.history.state, '', url); + window.history.replaceState(window.history.state, "", url); if ( compConfig.value.updateVueRouteOnSearch && @@ -711,11 +715,11 @@ export const useLimboSearch = async (options = {}) => { } // Edge case, but might as well handle it if ( - typeof window !== 'undefined' && + typeof window !== "undefined" && compConfig.value.updateVueRouteOnSearch && compConfig.value.updateUrlQueryOnSearch ) { - window.history.replaceState(window.history.state, '', oldUrl); + window.history.replaceState(window.history.state, "", oldUrl); } } @@ -728,12 +732,12 @@ export const useLimboSearch = async (options = {}) => { if ( compConfig.value.immediateSearch && (compConfig.value.immediateSearch?.ssr || - typeof compConfig.value.immediateSearch === 'boolean') + typeof compConfig.value.immediateSearch === "boolean") ) { resetPagination(); if ( compConfig.value.immediateSearch?.useUrlQuery || - typeof compConfig.value.immediateSearch === 'boolean' + typeof compConfig.value.immediateSearch === "boolean" ) { mixParametersFromUrl(); if (compConfig.value.enableGroupedSearch) { @@ -812,10 +816,10 @@ export const useLimboSearch = async (options = {}) => { const newPagination = {}; for (const key in pagination) { const value = pagination[key]; - if (typeof value?.limit !== 'undefined') { + if (typeof value?.limit !== "undefined") { newPagination[`l${key}`] = value.limit; } - if (typeof value?.offset !== 'undefined') { + if (typeof value?.offset !== "undefined") { newPagination[`o${key}`] = value.offset; } } @@ -838,7 +842,7 @@ export const useLimboSearch = async (options = {}) => { }); } } else { - field.value = value ?? ''; + field.value = value ?? ""; } return true; } @@ -852,21 +856,21 @@ export const useLimboSearch = async (options = {}) => { // Set key as pagination if (compConfig.value.enableGroupedSearch) { - const array = key.toLowerCase().split(''); + const array = key.toLowerCase().split(""); const firstLetter = array.shift(); - const remainder = array.join(''); + const remainder = array.join(""); if ( - (firstLetter === 'o' || firstLetter === 'l') && + (firstLetter === "o" || firstLetter === "l") && remainder === String(parseInt(remainder)) ) { const object = Object.assign( { limit: 0, offset: 0 }, internalPagination?.value?.[remainder] ); - if (firstLetter === 'o') { + if (firstLetter === "o") { object.offset = parseInt(value); } - if (firstLetter === 'l') { + if (firstLetter === "l") { object.limit = parseInt(value); } internalPagination.value = Object.assign( @@ -878,7 +882,7 @@ export const useLimboSearch = async (options = {}) => { continue; } } else { - if (key.toLowerCase() === 'limit') { + if (key.toLowerCase() === "limit") { if (!internalPagination.value) { internalPagination.value = { limit: parseInt(value), @@ -888,7 +892,7 @@ export const useLimboSearch = async (options = {}) => { } internalPagination.value.limit = parseInt(value); continue; - } else if (key.toLowerCase() === 'offset') { + } else if (key.toLowerCase() === "offset") { if (!internalPagination.value) { internalPagination.value = { limit: 0,