svelte-axios-plus
v2.0.0
Published
A Svelte-optimized Axios wrapper that provides reactive request handling, built-in caching, and simplified state management for HTTP requests.
Maintainers
Readme
svelte-axios-plus
A Svelte-optimized Axios wrapper that provides reactive request handling, built-in caching, and simplified state management for HTTP requests.
TOC
- Installation
- Compatibility
- Quickstart
- Documentation
- Guides
- Reactivity
- Playground
- Breaking changes
- Testing
- Promises
- Credits
- License
Installation
npm install axios svelte-axios-plus
axiosis a peer dependency and needs to be installed explicitly
Compatibility
Version 2.x.x of svelte-axios-plus is built for Svelte 5.
Users running Svelte 4 applications should continue using the latest 1.x.x version of svelte-axios-plus.
Full documentation for v1 is available in the v1 Readme.
Quickstart
<script lang="ts">
import axiosPlus from 'svelte-axios-plus';
const { req, refetch } = axiosPlus('https://reqres.in/api/users?delay=1');
</script>
{#if req.loading}
<p>Loading...</p>
{:else if req.error}
<p>Error!</p>
{/if}
<div>
<button onclick={() => refetch()}>Refetch</button>
<pre>{JSON.stringify(req.data, null, 2)}</pre>
</div>Documentation
API
The package exports one default export and named exports:
import axiosPlus, {
resetConfigure,
configure,
clearCache,
load,
getConfig,
makeAxiosPlus
} from 'svelte-axios-plus';axiosPlus(url | config | (() => url | config), options? | () => options)
The main function to execute HTTP requests.
Parameters
url|config- String URL or axios request configoptions- Configuration objectmanual(defaultfalse) - Controls automatic request execution on component render. Use therefetchfunction returned when invokingaxiosPlusto execute the request manually.useCache(defaulttrue) - Enables/disables request caching. It doesn't affect therefetchfunction returned byaxiosPlus.autoCancel(true) - Controls automatic cancellation of pending requests
[!IMPORTANT]
Default caching behavior can interfere with test isolation. See testing section.
Returns
An object with the following properties:
req- Request state objectdata- Response data from the axios success responseloading- Current request status (true if the request is in progress, otherwise false)error- Error details if request failedresponse- Complete success response object
refetch(configOverride?, options?)- Manual request executionconfig- Sameconfigobject asaxios, which is shallow-merged with the config object provided when invokingaxiosPlus.options.useCache(defaultfalse) - Enables/disables request caching- Returns: A promise containing the response. If the request is unsuccessful, the promise rejects and the rejection must be handled manually.
cancel()- Cancels pending requestsreset(force?)- Resets the request state to its initial stateforce(defaultfalse) - Forces a reset even if the request is in progress by cancelling the pending request
resetConfigure()
Resets all configuration options back to default values.
Default values:
axios-StaticAxiosinstancecache-new LRUCache({ max: 500, ttl: 1000 * 60 })defaultOptions-{manual: false, useCache: true, autoCancel: true}defaultLoadOptions-{useCache: true}
configure(options?)
Configures the axiosPlus instance with custom options.
Parameters
axios- Custom Axios instance or Axios-like clientcache- LRU cache instance or false to disable cachingdefaultOptions- Default options for all requests. It will be merged with the out of the box default options.manual- Controls automatic request execution on component render. Use therefetchfunction returned when invokingaxiosPlusto execute the request manually.useCache- Enables/disables request caching. It doesn't affect therefetchfunction returned byaxiosPlus.autoCancel- Controls automatic cancellation of pending requests
defaultLoadOptions- Default options forloadfunctionuseCache- Enables/disables request caching
clearCache()
Clears the current LRU cache if caching is enabled.
load(url|config, options?)
Performs a one-time request with optional caching.
Parameters
url|config- String URL or axios request configoptions.useCache(defaulttrue) - Enables/disables request caching
Returns
A promise with the following properties:
data- Response data from the axios success responseerror- Error details if request failedresponse- Complete success response object
getConfig()
Returns the current configured options.
Returns
An object with the following properties:
axios- Current Axios instancecache- Current LRU cache instance or false if disableddefaultOptions- Default options configurationdefaultLoadOptions- Default load options configuration
makeAxiosPlus(configureOptions?)
Creates a new axiosPlus instance with optional initial configuration.
Parameters
axios- Custom Axios instance or Axios-like clientcache- LRU cache instance or false to disable cachingdefaultOptions- Default options for all requests. It will be merged with the out of the box default options.manual- Controls automatic request execution on component render. Use therefetchfunction returned when invokingaxiosPlusto execute the request manually.useCache- Enables/disables request caching. It doesn't affect therefetchfunction returned byaxiosPlus.autoCancel- Controls automatic cancellation of pending requests
defaultLoadOptions- Default options forloadfunctionuseCache- Enables/disables request caching
Returns
Preconfigured axiosPlus instance with the same methods as the package's named exports but limited to the axiosPlus instance returned by makeAxiosPlus.
Guides
Configuration
Unless provided via the configure function, svelte-axios-plus uses the following defaults:
axios-StaticAxiosinstancecache-new LRUCache({ max: 500, ttl: 1000 * 60 })defaultOptions-{manual: false, useCache: true, autoCancel: true}defaultLoadOptions-{useCache: true}
These defaults may not suit your needs, for example:
- you may want a common base url for axios requests
- the default cache size and ttl may not be a suitable default
- you want to disable caching altogether
In such cases you can use the configure function to provide your custom implementation of both.
<script lang="ts">
import axiosPlus, { configure } from 'svelte-axios-plus';
import { LRUCache } from 'lru-cache';
import Axios from 'axios';
const axios = Axios.create({
baseURL: 'https://reqres.in/api'
});
const cache = new LRUCache({ max: 10 });
configure({ axios, cache }); // configure globally
axiosPlus.configure({ axios, cache }); // configure per instance
</script>Manual Requests
On the client, requests are executed when the component renders using the Svelte $effect rune.
This may be undesirable, as in the case of non-GET requests. By using the manual option you can skip the automatic execution of requests and use the return value of axiosPlus to execute them manually, optionally providing configuration overrides to axios.
In the example below we use axiosPlus twice. Once to load the data when the component renders, and once to submit data updates via a PUT request configured via the manual option.
<script lang="ts">
import axiosPlus from 'svelte-axios-plus';
const { req: getReq } = axiosPlus('https://reqres.in/api/users/1');
const { req: putReq, refetch } = axiosPlus(
{
url: 'https://reqres.in/api/users/1',
method: 'PUT'
},
{ manual: true }
);
async function updateData() {
try {
await refetch({
data: {
...getReq.data,
updatedAt: new Date().toISOString()
}
});
} catch (error) {
// Handle errors
}
}
</script>
{#if getReq.loading || putReq.loading}
<p>Loading...</p>
{/if}
{#if getReq.error || putReq.error}
<p>Error!</p>
{/if}
<div>
<button onclick={updateData}>Update data</button>
<pre>{JSON.stringify(putReq.data || getReq.data, null, 2)}</pre>
</div>Manual Cancellation
The cancel function allows you to terminate pending requests, whether initiated automatically or through the refetch method.
In the example below we use axiosPlus with its automatic and manual requests.
We can call the cancellation programmatically or via controls.
<script lang="ts">
import axiosPlus from 'svelte-axios-plus';
let pagination: Record<string, number> = $state({ per_page: 6, page: 1 });
const { req, refetch, cancel } = axiosPlus(() => ({
url: 'https://reqres.in/api/users?delay=5',
params: pagination
}));
function handleFetch() {
pagination = { ...pagination, page: pagination.page + 1 };
}
async function externalRefetch() {
try {
await refetch();
} catch (error) {
// Handle errors
}
}
</script>
<div>
<button onclick={handleFetch}>Refetch</button>
<button onclick={externalRefetch}>External Refetch</button>
<button disabled={!req.loading} onclick={cancel}>Cancel Request</button>
{#if req.loading}
<p>...loading</p>
{/if}
<pre>{JSON.stringify(req.data, null, 2)}</pre>
</div>Server Side Rendering
For server-side requests containing sensitive data like API keys, use the async load function instead of axiosPlus. This integrates with SvelteKit's server-side data loading pattern.
In Svelte you can load data for your page via the +page.server.ts file. The logic inside that file is only executed on the server. You can read more about that topic over here.
Create a
+page.server.tsfile for your routeimport axiosPlus from 'svelte-axios-plus'; interface PageServerLoad { (): Promise<{ rdata: any; error: string; }>; } export const load: PageServerLoad = async () => { const { data, error, response } = await axiosPlus.load('https://reqres.in/api/users?delay=1'); return { rdata: data, error: JSON.stringify(error, null, 2) }; }; export const ssr = true; export const csr = false;Access data in
+page.svelte<script lang="ts"> interface Props { data: { rdata: any; error: string; }; } let { data }: Props = $props(); </script> <pre>Data: {JSON.stringify(data.rdata, null, 2)}</pre><p>Error: {data.error}</p>
Multiple Hook Instances
For applications requiring different API configurations or caching strategies, makeAxiosPlus enables creation of independent axiosPlus instances.
This factory function returns a configured axiosPlus instance based on provided configuration.
Tip Use this to create pre-configured instances as an alternative to the global
configurefunction.
<script lang="ts">
import axios from 'axios';
import { makeAxiosPlus } from 'svelte-axios-plus';
const customAxiosPlus = makeAxiosPlus({
axios: axios.create({ baseURL: 'https://reqres.in/api' })
});
const { req, refetch } = customAxiosPlus('/users?delay=1');
</script>
{#if req.loading}
<p>Loading...</p>
{/if}
{#if req.error}
<p>Error!</p>
{/if}
<div>
<button onclick={() => refetch()}>Refetch</button>
<pre>{JSON.stringify(req.data, null, 2)}</pre>
</div>Reactivity
While axiosPlus is not inherently reactive to argument changes, you can enable reactivity through:
- Lazy evaluation
- The
$derivedrune - An
$effectrune with therefetchfunction
For detailed information on Svelte function reactivity, refer to:
Notable Feature: When using an options state object with axiosPlus, changes to this object automatically trigger reactive updates by default (see example below).
<script lang="ts">
import axiosPlus, { type AxiosPlusOptions } from 'svelte-axios-plus';
let options: AxiosPlusOptions = $state({
manual: true,
autoCancel: true,
useCache: true
});
// The following two axiosPlus calls are equivalent and will react to 'options' state changes
const { req: req1 } = axiosPlus('https://reqres.in/api/users?delay=5', options);
const { req: req2 } = axiosPlus('https://reqres.in/api/users?delay=5', () => options);
</script>1. Lazy Evaluation (Recommended)
The axiosPlus function offers flexible configuration through dynamic function arguments. You can pass both the config and options as functions, enabling axiosPlus to automatically respond to state changes in these function arguments.
Here's what makes this powerful:
- Pass config as a function:
axiosPlus(() => config) - Pass options as a function:
axiosPlus(config, () => options) - Pass both as functions:
axiosPlus(() => config, () => options)
The best part? You have complete flexibility - use functions for dynamic state values and plain objects for static configurations. This means you can mix and match based on your needs.
- Pros
- Implements Svelte's recommended approach for reactive state passing
- Preserves
axiosPlusinternal state integrity, with request cancellation controlled through theautoCancelflag
- Cons
- Introduces function parameters, slightly increasing the complexity of the
axiosPlusimplementation
- Introduces function parameters, slightly increasing the complexity of the
<script lang="ts">
import axiosPlus, { type AxiosPlusOptions } from 'svelte-axios-plus';
let pagination: Record<string, number> = $state({});
let options: AxiosPlusOptions = $state({
manual: true,
autoCancel: true,
useCache: true
});
const { req } = axiosPlus(
() => ({
url: 'https://reqres.in/api/users?delay=5',
params: pagination
}),
() => options
);
</script>2. Dervied method
Using the $derived rune with axiosPlus triggers a complete function reinitialization whenever any referenced state values are modified.
- Pros
- Simple implementation requiring only a
$derivedrune wrapper around theaxiosPlusfunction
- Simple implementation requiring only a
- Cons
- Reinitializing the entire
axiosPlusfunction resets its internal state and terminates active requests, regardless of theautoCancelsetting
- Reinitializing the entire
<script lang="ts">
import axiosPlus, { type AxiosPlusOptions } from 'svelte-axios-plus';
let pagination: Record<string, number> = $state({});
let options: AxiosPlusOptions = $state({
manual: true,
autoCancel: true,
useCache: true
});
const { req } = $derived(
axiosPlus(
{
url: 'https://reqres.in/api/users?delay=5',
params: pagination
},
options
)
);
</script>3. Effect method
Using the $effect rune to trigger the refetch function on state changes provides a robust and controlled approach to handling reactive updates.
- Pros
- Flexible state management without requiring initial state declaration in
axiosPlusinitialization - Maintains
axiosPlusinternal state integrity, with request cancellation controlled solely by theautoCancelsetting
- Flexible state management without requiring initial state declaration in
- Cons
- Requires additional implementation through the
$effectrune, increasing code footprint - Reactivity is limited to
configOverrideanduseCacheoptions, excluding other settings likemanualandautoCancel
- Requires additional implementation through the
<script lang="ts">
import axiosPlus, { type RefetchOptions } from 'svelte-axios-plus';
let pagination: Record<string, number> = $state({});
let options: RefetchOptions = $state({
useCache: true
});
const { req, refetch } = axiosPlus(
{
url: 'https://reqres.in/api/users?delay=5'
},
options
);
$effect(() => {
async function fetchData() {
try {
await refetch({ params: pagination }, options);
} catch (error) {
// Handle errors
}
}
fetchData();
});
</script>Playground
The project includes a very simple playground example to play around with the library and its features.
- Clone the repository
- Install dependencies via
npm install - Start the project via
npm run dev - Open the displayed url in your browser (most likely http://localhost:5173)
- Click on the Playground link
Breaking changes
General
- Requires Svelte 5
- The library now uses Svelte 5's runes system internally
- State management switched from Svelte 4 stores to Svelte 5's state management
Types & Interfaces
Renamed the following interfaces
ResponseValues->RequestStateOptions->AxiosPlusOptions
Updated the
AxiosPlusResulttype// Old type type AxiosPlusResult<TResponse = any, TBody = any, TError = any> = [ { loading: Readable<boolean>; data: Readable<TResponse | undefined>; error: Readable<AxiosError<TError, TBody> | null>; response: Readable<AxiosResponse<TResponse, TBody> | undefined>; }, RefetchFunction<TBody, TResponse>, () => void, () => void ]; // New type type AxiosPlusResult<TResponse = any, TBody = any, TError = any> = { req: Readonly<RequestState<TResponse, TBody, TError>>; refetch: RefetchFunction<TBody, TResponse>; cancel: () => void; reset: (force?: boolean) => void; };
Usage of axiosPlus
Due to the AxiosPlusResult type update the usage of axiosPlus has changed (see example below).
Further request state is now returned through the req property, and direct destructuring is no longer supported to maintain reactive state.
Version 1.x.x usage example
<script lang="ts"> import axiosPlus from 'svelte-axios-plus'; const [{ loading, data, error }, refetch] = axiosPlus('https://reqres.in/api/users?delay=1'); </script> {#if $loading} <p>Loading...</p> {:else if $error} <p>Error!</p> {/if} <div> <button on:click={refetch}>Refetch</button> <pre>{JSON.stringify($data, null, 2)}</pre> </div>Version 2.0.0 usage example
<script lang="ts"> import axiosPlus from 'svelte-axios-plus'; const { req, refetch } = axiosPlus('https://reqres.in/api/users?delay=1'); </script> {#if req.loading} <p>Loading...</p> {:else if req.error} <p>Error!</p> {/if} <div> <button onclick={() => refetch()}>Refetch</button> <pre>{JSON.stringify(req.data, null, 2)}</pre> </div>
Testing
Testing components that use axiosPlus may experience test isolation issues due to built-in caching. To ensure proper test isolation, call the configure function before each test to disable the cache:
configure({ cache: false });Promises
svelte-axios-plus requires ES6 Promise support. Check your environment's compatibility here.
For environments without ES6 Promise support, use some polyfill like this one ES6 promise.
Credits
svelte-axios-plus is heavily inspired by axios-hooks.
It began as a simple port of the axios-hooks package to svelte, but over the time I added some additional features that are not present in the axios-hooks package.
License
Dependencies:
