All Projects → lukesmurray → react-query-autosync

lukesmurray / react-query-autosync

Licence: other
A react hook which lets you automatically synchronize a value to a server with react-query

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language
HTML
75241 projects

Projects that are alternatives of or similar to react-query-autosync

next-saas
Rapid development of SaaS products with Next.js
Stars: ✭ 39 (+11.43%)
Mutual labels:  react-query
tmdb-viewer
A movie browsing/favoriting app
Stars: ✭ 63 (+80%)
Mutual labels:  react-query
keras-buoy
Keras wrapper that autosaves what ModelCheckpoint cannot.
Stars: ✭ 22 (-37.14%)
Mutual labels:  autosave
next-app-starter
Another awesome starter for your app base on nextjs + tailwind + react-query + react-hook-form + next-auth + jotai
Stars: ✭ 73 (+108.57%)
Mutual labels:  react-query
react-vite-admin
This Starter utilizes React, Recoil, React Query, React Hooks, Typescript, Axios And Vite. 全新技术栈的后台管理系统
Stars: ✭ 90 (+157.14%)
Mutual labels:  react-query
2021-nolto
부담없이 자랑하는 작고 소중한 내 프로젝트 🧸✨
Stars: ✭ 34 (-2.86%)
Mutual labels:  react-query
coderplex-org
Official Website for Coderplex Community. Built with Next.js and deployed on Vercel.
Stars: ✭ 32 (-8.57%)
Mutual labels:  react-query
VF-BlenderAutoSaveRender
Automatically saves a numbered or dated image after every render and can extend the Blender output path with dynamic variables
Stars: ✭ 34 (-2.86%)
Mutual labels:  autosave
react-query-blog-demo
An example repo I used to teach a React Query workshop
Stars: ✭ 82 (+134.29%)
Mutual labels:  react-query
vue-auto-storage
🍻 An automatic storage plugin for Vue2, persist the data with localStorage.
Stars: ✭ 84 (+140%)
Mutual labels:  autosave
awesome-react-query
A collection of awesome things regarding the React Query ecosystem
Stars: ✭ 67 (+91.43%)
Mutual labels:  react-query
react-query-helper
A helper library to use react-query more efficient, consistency
Stars: ✭ 133 (+280%)
Mutual labels:  react-query
expansion-pack
🔋 Useful stack expansion for ts-nextjs-tailwind-starter
Stars: ✭ 16 (-54.29%)
Mutual labels:  react-query
start-ui-native
🚀 Start UI [native] is an opinionated UI starter with ⚛️ React Native, ⬢ Native Base 3, ⚛️ React Query & 🐜 Formiz — From the 🐻 BearStudio Team
Stars: ✭ 62 (+77.14%)
Mutual labels:  react-query
ndaify-web
NDAify helps you keep your trade secrets under wraps 🔒
Stars: ✭ 33 (-5.71%)
Mutual labels:  react-query
github-jobs-client
Clone of GitHub Jobs website using the design from Frontend Mentor.
Stars: ✭ 22 (-37.14%)
Mutual labels:  react-query
use-mutation
🧬 Run side-effects safely in React
Stars: ✭ 81 (+131.43%)
Mutual labels:  react-query
hacker-news-client
Clone of Hacker News with modern design
Stars: ✭ 32 (-8.57%)
Mutual labels:  react-query
react-native-template
An opinionated template to bootstrap your next React Native app with all the time-wasting packages you need to have.
Stars: ✭ 132 (+277.14%)
Mutual labels:  react-query
Electrode
Web applications with node.js and React
Stars: ✭ 2,033 (+5708.57%)
Mutual labels:  react-query

useReactQueryAutoSync

A helpful react hook for building interfaces which require autosave. Read more about the motivation and design in the original blog post. Check out the quick example below or feel free to view the drawing demo online. The code for the demo is in the src folder and can be run locally with yarn dev. The hook is used in the useStrokes function in src/components/Demo.tsx.

Installation

# npm
npm install use-react-query-auto-sync

# yarn
yarn add use-react-query-auto-sync

Documentation

The library exposes two hooks useReactQueryAutoSync and useReactQueryAutoSave. Both hooks return an object which contains draft and setDraft properties which can be treated similarly to the state and setState values returned by useState. The key thing this library does is provide mechanisms to automatically save and load changes to the draft value between the server and the client, all through a simple API. Both hooks directly expose react query options so they are simple to configure and use. This is easiest to see with an example.

function Example() {
  const { draft, setDraft, queryResult } = useReactQueryAutoSync({
    queryOptions: { /* omitted but same as react-query */ },
    mutationOptions: { /* omitted but same as react-query */ },
    autoSaveOptions: { wait: 1000 },
  });

  const loading = queryResult.isLoading;

  if (loading) {
    return <div>Loading...</div>;
  } else {
    return (
      <div>
        <input type="text" value={draft} onChange={(e) => setDraft(e.target.value)}></input>
      </div>
    );
  }
}

In this example we use query and mutation options to tell useReactQueryAutoSync how to fetch and save the value to the server. We use the autoSaveOptions parameter to tell useReactQueryAutoSync to debounce changes and automatically synchronize the value to the server after one second without any changes.

Similarly to useState you can only change the draft value using the setDraft function.

In addition to the sync hook the library exposes useReactQueryAutoSave (save). The difference between the two is the save hook is unidirectional and only saves a local value to the server when the local value changes. This can be useful for automatically saving things like logs, user analytics, or error reports. The sync hook is useful for things like documents where you don't want the user to have to press a save button to keep their changes.

useReactQueryAutoSync Parameters

  • queryOptions required: these are the query options passed to useQuery. Make sure to set refetchInterval if you want to enable automatic polling. React query auto sync does not support query data selectors so make sure not to pass select. This is because react query auto sync expects the input to the mutate function to have the same type as the return value of the query function.
  • mutationOptions required: these are the mutation options passed to useMutation. Internally the hook uses onMutate, onError, and onSettled to optimistically update the state but it will call your versions of these functions as well. The hook uses the key previousData to save the previous data in the onMutate context.
  • autoSaveOptions: see autoSaveOptionsBelow. If undefined the hook will not automatically save data since it will assume a debounce time of Infinity.
  • merge: function used to merge updates from the server with local changes to server data. If undefined the hook will ignore background updates from the server even if refetchInterval is supplied and local changes will take precedence. The merge function is also used when an error occurs while saving data.
  • alertIfUnsavedChanges: ask the user to confirm before leaving the page if there are unsaved changes. If undefined the hook will not ask the user to confirm before leaving.
  • mutateEnabled: similar to the enabled parameter of useQuery. If mutateEnabled is false and the hook tries to save to the server, a pending save will be created, and when mutateEnabled is toggled to true the pending save will immediately execute. Can be useful if you need to use dependent queries to get data to perform the mutation. If undefined, mutateEnabled defaults to true.
  • draftProvider: experimental see draftProviderBelow. If undefined the hook will use useState to create the draft value.

useReactQueryAutoSave Parameters

Same as useReactQueryAutoSync but does not have queryOptions.

autoSaveOptions

  • wait: number of milliseconds to delay the debounce function
  • maxWait: maximum number of milliseconds to delay the debounce function. If undefined there is no max delay.

draftProvider (experimental)

  • draft: The current value of the draft.
  • setDraft: Function used to update the draft. (value) => void.

By default useReactQueryAutoSync uses useState to implement the draft. However there are times when this is not desired. For example, if you want to display the same synchronized value in multiple places in your application you have to either lift state up or use a react context. If you try using useReactQueryAutoSync in multiple locations the values may eventually sync but it would be a sub optimal experience since synchronizing the values would require multiple round trips to the server. Instead you can use the draftProvider and provide your own draft values backed by a library such as recoil or jotai or zustand. Here is a simple example which creates a draftProvider using jotai. Regardless of where you use this hook the draft values will be immediately synchronized.

const exampleAtom = atom(undefined);

function Example() {
  const [draft_, setDraft_] = useAtom(exampleAtom);
  const { draft, setDraft, queryResult } = useReactQueryAutoSync({
    queryOptions: { /* omitted */ },
    mutationOptions: { /* omitted */ },
    autoSaveOptions: { wait: 1000 },
    draftProvider: { draft: draft_, setDraft: setDraft_ },
  });

⚠️ This is an experimental feature and has issues such as potentially issuing a mutation for each hook.

For instructions on how to use draftProvider safely check this issue comment.

Example

Here is a more complex example which shows off more of the features of useReactQueryAutoSync.

import React from "react";
import { useReactQueryAutoSync } from "../lib/useReactQueryAutoSync";

// fake api object. You would supply your own!
const fakeAPI: any = {};

// fake function used to merge server and local state
const mergeFoo: any = (remote: any, local: any) => ({ ...remote, ...local });

export function Demo() {
  const { draft, setDraft } = useReactQueryAutoSync({
    queryOptions: {
      queryKey: "foo",
      queryFn: async () => fakeAPI.fetchFoo(),
      // if you want to poll the server pass a refetchInterval to react query
      refetchInterval: 5000,
    },
    mutationOptions: {
      mutationFn: async (foo) => fakeAPI.saveFoo(foo),
    },
    // pass autoSaveOptions to automatically save to the server with debouncing
    autoSaveOptions: {
      wait: 500,
    },
    // pass alertIfUnsavedChanges to notify user if they leave with unsaved changes
    alertIfUnsavedChanges: true,
    // pass merge to merge server and local state when the server state updates
    merge: (remoteFoo, localFoo) => mergeFoo(remoteFoo, localFoo),
  });

  return (
    <>
      <input
        type="text"
        value={draft.foo}
        onChange={(e) => {
          // modify draft with `setDraft` but make sure to modify a copy so you
          // don't break the ReactQuery caching!
          setDraft({ ...draft, foo: e.target.value });
        }}
      />
    </>
  );
}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].