Skip to content

Repository files navigation

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, and AsyncData wrapping Option<T>
  • Built-in caching with auto revalidation & manual refresh
  • Supports React & Vue with idiomatic hooks/composables
  • Reactive watch dependencies 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";functionUserProfile({ userId }: {userId: string}){const[state,refetch]=useValync<{name: string;age: number}>(`/api/user/${userId}`,{fetchOnMount: true,retryCount: 2,},);returnstate.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";exportdefault{setup(){const[state,refetch]=useValync("/api/user/123",{fetchOnMount: true,});constuserDisplay=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

React demo counter

Vue demo counter

Axios or other HTTP client

importaxiosfrom"axios";import{createValyn}from"valync/react";constuseAxiosValync=createValyn({client: async(url,init)=>awaitaxios({ url, ...init}).then((res)=>{"status": "success";"data": res.data}),// transforms to data});// use in a componentconst[state,refetch,setData]=useAxiosValync<User>("/api/user",{onData: (data)=>{// transform data to User if neededreturndata;},});

☕️ 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 🍻

👉 Send me a drink on Cointr.ee

About

A lightweight, framework-agnostic async data handling library for React & Vue, inspired by Riverpod’s AsyncValue pattern and powered by ts-results-es

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages