Api
Centralized API handling system with built-in caching and configurable request behavior.
Features
All request methods are centrally defined.
- centralized HTTP methods
- single base URL setup
- built-in GET caching
- cache invalidation helpers
- supports custom request logic and transformation
- conditional behavior based on request metadata
- auth handling
Supported methods:
get,post,put,deletepatch,head,options
Api.setContext()
Define how requests should execute internally.
Usually called once at app startup.
Example
import { Api } from "..";
Api.setContext({
get: async (url, config) => {
// config is queryConfig
const data = await axios.get(`${BASE_URL}/${url}`, {
headers: config.headers,
});
return data;
},
post: async (url, data, config) => {
// ...
},
// other methods...
});Anything passed through queryConfig becomes available inside the context.
Example:
config.headers;
config.myData;Api.get()
Perform GET requests with optional caching.
Api.get(url, config?)Example
const data = await Api.get("/users", {
queryConfig: {
headers: {
token: "123",
},
myData: {
role: "admin",
},
},
cache: 45,
});Config Options
| Option | Description |
|---|---|
queryConfig | Custom data passed into request context |
cache | Cache duration in seconds |
cacheKey | Custom cache identifier |
GET Cache
Caching is available only for GET requests.
Default cache duration:
0;meaning no caching.
Global Cache Duration
Api.setDefaultCacheDuration(60);All GET requests now cache for 60s.
Example
Api.get("/users");If called again within the cache duration, cached data is returned instead of making another network request.
After expiration, a fresh request is made automatically.
Per-request Cache
You can override cache duration per request.
Api.get("/live-score", {
cache: 0,
});Useful for real-time endpoints.
Cache Keys
Cache is stored using:
url -> responseExample:
Api.get("/users");stored as:
'/users': responseCache Collision Problem
These two requests are different:
Api.get("/users");
Api.get("/users", {
queryConfig: {
headers: {
role: "admin",
},
},
});But both share the same cache key:
/userswhich can override previous cache.
Solution: cacheKey
Api.get("/users");
Api.get("/users", {
queryConfig: {
headers: {
role: "admin",
},
},
cacheKey: "users-by-role",
});Stored internally as:
/users::users-by-roleCache Invalidation
Stale Data Problem
Example:
await Api.post("/addUser", {
name: "John",
});Then:
Api.get("/users");may still return old cached data.
invalidateCache()
Remove specific GET cache entries manually.
Api.invalidateCache(
url,
cacheKey? // pass if present in GET call
);Example
await Api.post("/addUser", {
name: "John",
});
Api.invalidateCache("/users");Now the next GET request fetches fresh data from the network.
clearCache()
Clear all stored GET cache.
Api.clearCache();Component Usage
Since components run only once, APIs that do not depend on reactive values can be called directly without wrapping inside effects.
Example
function Posts() {
const posts = state(list([]));
const getPosts = async () => {
const data = await Api.get("/posts");
posts.set(data);
};
getPosts();
return (
<div>
<For each={posts()}>{(post) => <p>{post.title}</p>}</For>
</div>
);
}When to use outside setEffect()
If the API does not depend on changing reactive values, it can run directly inside the component body.
Since components execute only once, the request will not repeat on state updates.
Call Api in setEffect when it depends on some state.
Example: when user change filter, posts should re-fetched which is done using setEffect.
function Posts() {
const posts = state(list([]));
const filters = state({ sort: "ASC" });
const getPosts = async () => {
const data = await Api.get("/posts", {
queryConfig: { filters: filters() },
});
posts.set(data);
};
setEffect(() => {
getPosts();
}, [filters]);
return (
<div>
<button onClick={() => filters.set((f) => ({ ...f, sort: "DESC" }))}>
Change order of Posts
</button>
<For each={posts()}>{(post) => <p>{post.title}</p>}</For>
</div>
);
}