valync
Valync
A lightweight, framework-agnostic async data handling library for React & Vue, inspired by Riverpod’s AsyncValue pattern and powered by ts-results-es.
Features
- Unified async state with
AsyncLoading,AsyncError, andAsyncDatawrappingOption<T> - Built-in caching with auto revalidation & manual refresh
- Supports React & Vue with idiomatic hooks/composables
- Reactive
watchdependencies to refetch on data change setData()for manual or partial UI updates- Uses a strict API response shape for uniform error & data handling
- Flexible Mutations / Write operations to API
Installation
Npm
npm i valync
yarn
yarn add valync
Bun
bun add valync
API Overview
useValync<T>(key, options?)
A hook/composable to fetch and manage async data.
key: string | Record<string, any>— Unique cache key or URL.options?:
{
init?: Omit<RequestInit, "signal">; // Pass request options for default client or custom client
cache?: boolean; // default true, enable/disable caching
fetchOnMount?: boolean; // default true, fetch automatically on mount
retryCount?: number; // retry count for failed requests
onData?: (data: T) => T; // transform data before setting
watch?: any[]; // reactive dependencies to trigger refetch
initialData?: ApiResponse<T>; // initial server-side data for hydration
fetchInterval?: number;
onSuccess?: (data: T) => void;
onError?: (err: ApiErrorResponse["error"]) => void;
}
Return tuple
const [state, refetch, setData] = useValync<T>(key, options);
AsyncValue States
AsyncLoading<T>;
AsyncError<T>; // contains error { name, message, code? }
AsyncData<T>; // contains Option<T>: Some(value) or None
Example usage
React
import { useValync, AsyncValue } from "@epikoder/valync-react";
function UserProfile({ userId }: { userId: string }) {
const [state, refetch] = useValync<{ name: string; age: number }>(
`/api/user/${userId}`,
{
fetchOnMount: true,
retryCount: 2,
},
);
return state.when({
loading: () => <div>Loading...</div>,
error: (err) => <div>Error: {err.message}</div>,
data: (opt) =>
opt.some ? (
<div>
{opt.val.name} ({opt.val.age} years old)
</div>
) : (
<div>No data available</div>
),
});
}
const [state, onLogin] = useValync("/api/auth", {
cache: false,
fetchOnMount: false,
init: {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
},
});
Vue 3
import { useValync, AsyncValue } from "@epikoder/valync-vue";
import { computed } from "vue";
export default {
setup() {
const [state, refetch] = useValync("/api/user/123", {
fetchOnMount: true,
});
const userDisplay = computed(() =>
state.when({
loading: () => "Loading...",
error: (e) => `Error: ${e.message}`,
data: (opt) => (opt.some ? `${opt.val.name}` : "No user"),
}),
);
return { userDisplay, refetch };
},
};
for use within template you can use state.isLoading(), state.isData() and state.isError().
For more usage check the examples
Axios or other HTTP client
import axios from "axios";
import { createValync } from "valync/react";
const useAxiosValync = createValync({
client: async (url, init) =>
await axios({ url, ...init }).then((res) => {"status": "success"; "data": res.data}), // transforms to data
});
// use in a component
const [state, refetch, setData] = useAxiosValync<User>("/api/user", {
onData: (data) => {
// transform data to User if needed
return data;
},
});
☕️ Buy Me a Drink
If this project saved you time, helped you ship faster, or made you say "damn, that's slick!" — consider buying me a beer 🍻
Related Packages
stunk
A lightweight, framework-agnostic state management library for JavaScript and Ty...
20,759
173
@syntropysoft/syntropyfront
One line of code to capture frontend errors and user actions. Low cost, no per-s...
2,273
0
hy-event-store
A zero-dependency event bus and global state store for Vue, React, Mini Programs...
1,342
411
@favorodera/use-promise
A Vue composable for managing async operations with reactive state, cancellation...
1,225
1
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.4.2 | ^3.0.0 | ||
| 0.4.1 | ^3.0.0 | ||
| 0.4.0 | ^3.0.0 | ||
| 0.3.4 | ^3.0.0 | ||
| 0.3.3 | ^3.0.0 | ||
| 0.3.2 | ^3.0.0 | ||
| 0.3.1 | ^3.0.0 | ||
| 0.3.0 | ^3.0.0 | ||
| 0.2.8 | ^3.0.0 | ||
| 0.2.7 | ^3.0.0 | ||
| 0.2.5 | ^3.0.0 | ||
| 0.2.4 | ^3.0.0 | ||
| 0.2.3 | ^3.0.0 | ||
| 0.2.2 | ^3.0.0 | ||
| 0.2.1 | ^3.0.0 | ||
| 0.2.0 | ^3.0.0 | ||
| 0.1.1 | ^3.0.0 | ||
| 0.1.0 | ^3.0.0 |
Pre-releases (2)
| Version | Released | Vue | License |
|---|---|---|---|
| 0.3.1-beta | ^3.0.0 | ||
| 0.3.1-alpha | ^3.0.0 |