npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

snap-fetch

v1.1.25

Published

## FEATURES

Downloads

119

Readme

Snap-Fetch Overview

FEATURES

  • Pagination Support for all queries
  • Caching and Invalidation
  • Adjustable cache expiration time
  • Automatic Refetching on Network Reconnect
  • Transform Response Functionality
  • Stale While Revalidate (SWR) Pattern
  • Out of the box duplicate requests prevention
  • Global and Individual (Query and Mutation) Configurations
  • Request Debouncing
  • New features will be added soon...

WHAT WE'LL LEARN

  • What snap-fetch is and what problems it solves
  • What APIs are included in snap-fetch
  • Basic usage

snap-fetch

snap-fetch is a light weight data fetching tool built for React that allows you to fetch data from an API, cache it, and store it in Redux using Redux Toolkit and Redux Snap. It provides intuitive hooks for performing *8queries** and mutations, as well as a hook for configuring **global api options**.

Motivation

Web applications typically require data from a server in order to display it. They also typically need to update that data, communicate those modifications to the server, and maintain the cached data on the client in sync with the data on the server. This is made more hard by the requirement to include additional behaviors utilized in today's applications:

  • Tracking the loading state to show UI spinners.
  • Avoiding multiple requests for the same data.
  • Optimistic updates make the UI feel quicker.
  • Managing cache lifetimes as the user interacts with the UI.

Installation

You can install snap-fetch using npm or yarn:

npm install snap-fetch

or

yarn add snap-fetch

Add SnapFetch Sagas and Reducers To Your Redux Store

Add Snap Reducers

import { name, reducer } from "snap-fetch";

export const rootReducer = combineReducers({
  [name]: reducer,
});

Run SnapFetch Sagas

/**
 * Create the store with dynamic reducers
 */

import { configureStore } from "@reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import { rootReducer } from "./reducers";
import { rootSnapFetchSaga } from "snap-fetch";

export function configureAppStore() {
  const sagaMiddleware = createSagaMiddleware();

  // Create the Redux store with middleware
  const store = configureStore({
    reducer: rootReducer,
    middleware: (getDefaultMiddleware) =>
      getDefaultMiddleware({
        serializableCheck: false,
      }).concat(sagaMiddleware),
  });

  // Run the root Snap
  sagaMiddleware.run(rootSnapFetchSaga);
  return { store };
}

What's included

  1. useSetBaseConfiguration
  2. useSnapQuery
  3. useSnapMutation

useSetBaseConfiguration (Base Configuration)

The useSetBaseConfiguration hook is used to configure the base options for Snap.

Usage

useSetBaseConfiguration(options);

Parameters

  • options (object): The configuration options.

Options

The options object accepts the following properties:

  • baseUrl (string, required): The base URL for the API. (Required)
  • disableCaching (boolean): If set to true, caching will be disabled, can be overridden by individual query options.
  • cacheExpirationTime (number default to 90 sec): The cache expiration time in seconds, can be overridden by individual query options.
  • customFetchFunction ((endpoint: string) => Promise(Response)): A custom fetch function to use for making API requests. If you don't want to use the built in fetcher.
  • headers (Headers): Additional headers to be included in each request.
  • disableRefetchOnReconnect (boolean) disable refetching on reconnect for all queries if true, can be overridden by individual disableRefetchOnReconnect properties on individual queries.
  • skipAuth (boolean, optional) Skip authorization header for all queries and mutation if true, can be overridden by individual skipAuth properties on individual queries and mutations.
  • debounce (number) Debounce time for all queries if true, can be overridden by individual debounce properties on individual queries.
  • Axios API Configs...
// To root of you project like App.tsx main.tsx

import { useSetBaseConfiguration } from "snap-fetch";
const baseUrl = "https://jsonplaceholder.typicode.com";

useSetBaseConfiguration({
  baseUrl, // Required
  disableCaching: boolean, // if true caching will be disabled, // this is global, can be overridden by individual disableCaching properties
  // Below has no effect if you are using your own fetch function
  headers: new Headers({
    Authorization: `Bearer ${token}`,
  }),
});

useSnapQuery (Query Hook)

This hook allows you to fetch data from the server using the Snaps and store it in the redux store, it is configured to know if the same endpoint is called with the same queryParams, it would only refetch data if the cache is empty or mutated by mutation, or if queryParams are changed...

It uses the endpoint + queryParams to cache the state, which allow it to avoid unnecessary fetch requests.

it accepts two parameters

  1. The endpoint - is the endpoint which will be used to fetch data by combining with the baseUrl
  2. Request options - is as follows:
type RequestOptions = {
  method?: Method,
  disableCaching?: boolean, // will disable caching for the current endpoint request
  fetchFunction?: (endpoint: string) => Promise<Response>, // custom fetch function if you don't like the built-in.
  tags?: Tags, // Tags will be used to invalidate on mutation requests.
  filter?: { [key: string]: number | boolean | string | undefined | null }, // your filters except for pagination.
  pollingInterval?: number, // polling interval for polling requests
  skip?: boolean, // skip on mount request for the current endpoint
  single?: boolean, // to tell the snap-fetcher query you don't want to use pagination.
};

Query Result

The useSnapQuery hook returns a query result object with the following properties: useSnapQuery is a generic type function, the type is used to tell the type of the data returned from the api call.

  • data (T | undefined): The fetched data.
  • isLoading (boolean): A flag indicating if the query is in progress.
  • isError (boolean): A flag indicating if an error occurred during the query.
  • error (Error | undefined): The error object, if any.
  • paginationOptions (object): The pagination options for the query.
  • refetch (function): A function to manually trigger a refetch of the query.

Pagination Options

Queries have built in pagination support the result of useSnapQuery will return a paginationOptions object with the following properties:


{
    lastPage: number;
    currentShowingItems: number | undefined;
    totalItems: number;
    changePageNo: (pageNo: number) => void;
    changeSize: (size: number) => void;
    pageNo: number;
    size: number;
}
  • Use the the changePageNo and changeSize to update the pagination.

Usage

Import the necessary hooks from the snap-fetch package:

import { useSnapQuery } from "snap-fetch";

2. Querying Data

const MyComponent = () => {
  const { data, isLoading, error } =
    useSnapQuery <
    Users >
    ("users",
    {
      tags: "getUsers",
    });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      {data.map((user) => (
        <div key={user.id}>{user.name}</div>
      ))}
    </div>
  );
};

useSnapMutation (Mutation Hook)

This hook allows you to manipulate the data and make mutation calls it will automatically revalidate the cache if queries with the same endpoint are available.

It accept two parameters:

  1. The endpoint
  2. Options:
type RequestOptions = {
  method?: Method,
  fetchFunction?: (endpoint: string) => Promise<Response>, // custom fetch function if you don't like the built-in.
  invalidateTags?: Tags, // Tags will be used to invalidate on mutation requests.
  body?: any, // Request body, will automatically remove the body if you accidentally use methods like "GET" or "HEAD"
};

Mutation Result

  • data (T | undefined): The returned data.
  • isLoading (boolean): A flag indicating if the query is in progress.
  • isError (boolean): A flag indicating if an error occurred during the query.
  • error (Error | undefined): The error object, if any.
  • mutate (function): A function to trigger a fetch request.

3. Mutating Data

To perform a mutation and send data to the API, use the useSnapMutation hook. Here's an example:

const MyComponent = () => {
  const { mutate, isLoading, error } = useSnapMutation("createUser", {
    invalidateTags: ["getUsers"],
  });

  const handleSubmit = async (data) => {
    try {
      await mutate(data);
      console.log("User created successfully!");
    } catch (e) {
      console.error("Error creating user:", e);
    }
  };

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error.message}</div>;
  }

  return (
    <div>
      <form onSubmit={handleSubmit}>
        {/* form fields */}
        <button type="submit">Create User</button>
      </form>
    </div>
  );
};

For further information please see the full documentation.