-
-
Notifications
You must be signed in to change notification settings - Fork 5k
Closed
Description
What problem does this feature solve?
Currently having an issue where I want to
- Create a nested router-view
- Do some API fetching in the parent
- Pass down data to all the children components
- Have the children re-render when the reactive values update
What I tried was this
/* my-view.vue */
<template>
<router-view
:data="data"
:loading="loading"
:error="error"
:lastUpdated="lastUpdated"
/>
</template>
<script>
import { useAPIRequest } from '@/hooks/useAPIRequest';
export default {
setup() {
/* this will make the API request on mount and update the appropriate values on resolve/reject */
const {
data,
loading,
error,
lastUpdated,
} = useAPIRequest(
() => Promise.resolve([]),
);
return {
data,
loading,
error,
lastUpdated,
};
},
};
</script>
<style lang="scss" scoped></style>/* useAPIRequest.js */
import { ref } from '@vue/composition-api';
/**
*
* @param { () => Promise<any> } request
* @param { any } initialData
*
* @returns {
* loading: boolean;
* error: any;
* lastUpdated: number;
* data: any;
* }
*/
export const useAPIRequest = (
request,
initialData,
) => {
const data = ref(initialData || null);
const loading = ref(true);
const error = ref(null);
const lastUpdated = ref(0);
const handleRequest = () => {
if (!request) {
return Promise.resolve();
}
if (lastUpdated.value === 0) {
loading.value = true;
}
return request()
.then((response) => {
data.value = response;
loading.value = false;
lastUpdated.value = Date.now();
error.value = null;
})
.catch((err) => {
error.value = err;
loading.value = false;
});
};
handleRequest();
return {
data,
loading,
error,
lastUpdated,
update: handleRequest,
};
};
export default useAPIRequest;But this doesn't work because the components that are rendered in the nested routes have access to these values through attrs.data, attrs.loading, attrs.lastUpdated, etc. They are not reactive and the children components don't re-render when these values change
What ended up working for me was passing the values down as refs, like so
/* my-view.vue */
<template>
<router-view
:data="data"
:loading="loading"
:error="error"
:lastUpdated="lastUpdated"
/>
</template>
<script>
import { computed } from '@vue/composition-api';
import { useAPIRequest } from '@/hooks/useAPIRequest';
export default {
setup() {
const {
data,
loading,
error,
lastUpdated,
} = useAPIRequest(
() => Promise.resolve([]),
);
return {
data: computed(() => data),
loading: computed(() => loading),
error: computed(() => error),
lastUpdated: computed(() => lastUpdated),
};
},
};
</script>
<style lang="scss" scoped></style>But I'm assuming passing down refs is an anti-pattern and probably isn't recommended.
My ask is that I want the ability to pass down reactive values to <router-view /> children and have them re-render when these values change
What does the proposed API look like?
Possibly <router-view render="(Component => <Component myProp="something" />)" />
Metadata
Metadata
Assignees
Labels
No labels