-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a way to reload a failed async component #9788
Comments
I personally always felt the factory function was too high level for Vue. When using a user-side solution like vue-promised or a custom implementation, it's so much more flexible and you can deal with everything |
This can help to solve the problem, it's hacky but it works.
|
@bogdanmatra I tried your solution, it's useless when async, and dead when sync (same code above). I modified your code to this: // import...
/** get AsyncComponent with loading status
* @param {Function: () => Promise<Component | { default: Component }>} promiseFactory eg: () => import('Component')
*
* @returns {Component} AsyncComponent
*/
function getAsync(promiseFactory, loading = LOADING, error = ERROR) {
const asyncComponentFactory = () => () => ({
error,
loading,
component: promiseFactory(),
delay: 1,
timeout: 15000,
})
const observe = Vue.observable({ c: asyncComponentFactory() })
return {
functional: true,
render(createElement, { data, children }) {
// emit event $ to reloading
if (data.on ? !data.on.$ : (data.on = {})) {
data.on.$ = () => {
observe.c = asyncComponentFactory()
// parent.$forceUpdate()
}
}
return createElement(observe.c, data, children)
},
}
} And error.vue <template>
<div @click="$emit('$')">Loading failed, click me to reloading</div>
</template> |
Good work on this example! I figured I would donate my modification to make it work with @vue/composition-api and typescript. Comments welcome! // would import these directly from vue if not using the @vue/composition-api plugin
import {
defineComponent,
ref,
defineAsyncComponent,
h
} from '@vue/composition-api'
import AsyncError from './async-error.vue' // default error component
import AsyncLoading from './async-loading.vue' // default loading component
// this is a hack to get the type of the first parameter since it isn't exported from @vue/composition-api
export type AsyncComponentSource = Parameters<typeof defineAsyncComponent>[0]
export const withReload = (
source: AsyncComponentSource,
initialProps: Record<string, unknown> = {
loadingMessage: 'Setting some things up for you...'
}
) =>
defineComponent({
setup(props, ctx) {
const asyncComponentFactory = () =>
defineAsyncComponent({
loadingComponent: AsyncLoading,
errorComponent: AsyncError,
...('loader' in source ? source : { loader: source })
// uncomment this if you want to test the $reload function by artifically adding latency to the resolution of the module
// loader: () =>
// new Promise(resolve => setTimeout(resolve, 3000)).then(
// () => import('./async-error.vue')
// )
})
const asyncComponent = ref(asyncComponentFactory())
return () =>
// I'm not sure how to best pass through the props, data, and children, but this is my best guess given the current state of documentation
h(asyncComponent.value, {
...ctx,
props: {
...(props as Record<string, unknown>),
...initialProps
},
on: {
...ctx.listeners,
$reload() {
asyncComponent.value = asyncComponentFactory()
}
}
})
}
}) Here is how you would call it withReload(() => import('./path/to/component.vue')
// or
withReload({
loader: () => import('./path/to/component.vue'),
loadingComponent: SomeOtherLoadingComponent,
errorComponent: SomeOtherErrorComponent,
delay: 400 // other options supported too
}) <template>
<div @click="$emit('$reload')">Loading failed, click me to reloading</div>
</template> |
Closing as this should go through the RFC process in the rfcs repository |
Woking with me. |
What problem does this feature solve?
Local register a async component by a factory function that return an object to handling loading state. But when the promise is rejected, there will be always show error component and no any way to reload it.
What does the proposed API look like?
listen replaced component's(loading/error) events and the event context allows to change loading state(rerend, of course)
The text was updated successfully, but these errors were encountered: