Skip to content

Instantly share code, notes, and snippets.

@ktsn
Created March 1, 2019 07:47
Show Gist options
  • Save ktsn/48e1c7c50528885291ea15a9f79a0868 to your computer and use it in GitHub Desktop.
Save ktsn/48e1c7c50528885291ea15a9f79a0868 to your computer and use it in GitHub Desktop.
Yet another way to handle loading state and store data instead of scoped slots in Vue.js
<template>
<div v-if="posts.loading">Loading...</div>
<ul v-else>
<li v-for="p in posts.data" :key="p.id">{{ p.title }}</li>
</ul>
</template>
<script lang="ts">
import Vue from 'vue'
import { connectPosts } from './connect-posts'
export default Vue.extend({
data() {
return {
// Initial state:
// {
// loading: true
// data: []
// }
//
// It automatically load the data under hood and
// is updated to:
// {
// loading: false
// data: [
// { id: '...', title: '...' },
// ...
// ]
// }
posts: createPosts(this.$store)
}
}
})
</script>
import { createConnector } from './connector'
interface Post {
id: string
title: string
}
export const connectPosts = createConnector<Post[]>(store => {
return {
exists: () => store.state.loaded,
fetch: () => store.dispatch('fetchPosts'),
data: () => store.state.posts
}
})
import { Store } from 'vuex'
export interface Connector<T> {
readonly loading: boolean
readonly data: T
}
export interface CreateConnector<T> {
(store: Store<any>, options?: ConnectorOptions): Connector<T>
config: (store: Store<any>) => ConnectorConfig<T>
}
export interface ConnectorConfig<T> {
exists: () => boolean
fetch: () => Promise<any>
data: () => T
}
export type FetchPolicy = 'cache-first' | 'cache-and-network'
export interface ConnectorOptions {
fetchPolicy?: FetchPolicy
}
export function createConnector<T>(
fn: (store: Store<any>) => ConnectorConfig<T>
): CreateConnector<T> {
function createConnector(
store: Store<any>,
options: ConnectorOptions = {}
): Connector<T> {
const fetchPolicy = options.fetchPolicy || 'cache-first'
const { exists, fetch, data } = fn(store)
if (fetchPolicy !== 'cache-first' || !exists()) {
fetch()
}
return {
get loading() {
return !exists()
},
get data() {
return data()
}
}
}
createConnector.config = fn
return createConnector
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment