Created
January 8, 2025 14:22
-
-
Save nash403/bb3c4f4eb62cda9535a335879c9c28a6 to your computer and use it in GitHub Desktop.
Revisions
-
nash403 created this gist
Jan 8, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,28 @@ # Dynamic composable loading with Vue 3 Reactive watcher to load effect scopes dynamically depending on the watched value. Typically, the effect scope you load is a function that contains reactive logic in the same way you would have in a component setup function. Example use: ```js const watchSource = ref(...) // anything const composableReturnState = watchCreateEffectScope(watchSource, (watchValue) => { /* * This function is like a watcher callback. It gets called with the new value everytime the `watchSource` changes. * You can execute whatever code you would normally execute in a component setup function. Everytime the `watchSource` * value changes, all effects loaded previously gets disposed, and the callback function gets re-executed, * loading any new effects. */ if (watchValue) { return composable1(); } else { return composable2(); } }); // `composableReturnState` is a ref containing the state of the loaded effect. ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,38 @@ import { useAsyncState, tryOnScopeDispose } from '@vueuse/core'; import { watch, ref, effectScope } from 'vue'; export function watchCreateEffectScope( watchSource, effectScopeFn, defaultEffectState = null, { immediate = true, ...options } = {} ) { let effState = ref(null); let effScope; const dispose = () => { effScope && effScope.stop(); effState.value = null; }; watch( watchSource, (newWatchedValue) => { try { dispose(); // first, dispose any previously loaded effect effScope = effectScope(); const composable = () => effectScopeFn(newWatchedValue); effState.value = effScope.run(composable); } catch (error) { console.error('Failed to load composable:', error); return defaultEffectState; } }, { immediate, ...options } ); tryOnScopeDispose(dispose); return effState; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,46 @@ export function watchCreateEffectScopeAsync( watchSource, asyncEffectScopeFn, defaultEffectState = null, { immediate = true, resetOnExecute = false, delay = 0, ...options } = {} ) { let effState, effScope; const dispose = () => { effScope && effScope.stop(); effState = null; }; const returnState = useAsyncState( async (watchedValue) => { try { dispose(); // first, dispose any previously loaded effect effScope = effectScope(); const composable = await asyncEffectScopeFn(watchedValue); effState = effScope.run(() => composable()); return effState; } catch (error) { console.error('Failed to load composable:', error); return defaultEffectState; } }, defaultEffectState, { resetOnExecute, ...options, immediate: false, // Keep as is. Set the watcher's immediate option below instead. } ); watch( watchSource, (newWatchedValue) => returnState.execute(Number(delay) || 0, newWatchedValue), { immediate, ...options } ); tryOnScopeDispose(dispose); return returnState; }