Installations
npm install use-react-query-auto-sync
Developer Guide
Typescript
Yes
Module System
CommonJS, ESM
Score
68.4
Supply Chain
92.8
Quality
75.3
Maintenance
100
Vulnerability
99.6
License
Releases
Unable to fetch releases
Contributors
Unable to fetch Contributors
Languages
TypeScript (75.61%)
JavaScript (23.56%)
HTML (0.83%)
Developer
Download Statistics
Total Downloads
43,867
Last Day
183
Last Week
512
Last Month
1,613
Last Year
14,083
GitHub Statistics
46 Stars
40 Commits
5 Forks
3 Watching
7 Branches
2 Contributors
Bundle Size
6.00 kB
Minified
2.16 kB
Minified + Gzipped
Package Meta Information
Latest Version
0.1.0
Package Id
use-react-query-auto-sync@0.1.0
Unpacked Size
774.92 kB
Size
241.32 kB
File Count
22
Total Downloads
Cumulative downloads
Total Downloads
43,867
Last day
105.6%
183
Compared to previous day
Last week
48.8%
512
Compared to previous week
Last month
19%
1,613
Compared to previous month
Last year
-5.5%
14,083
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
1
Peer Dependencies
3
Dev Dependencies
32
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
1# npm 2npm install use-react-query-auto-sync 3 4# yarn 5yarn 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.
1function Example() {
2 const { draft, setDraft, queryResult } = useReactQueryAutoSync({
3 queryOptions: { /* omitted but same as react-query */ },
4 mutationOptions: { /* omitted but same as react-query */ },
5 autoSaveOptions: { wait: 1000 },
6 });
7
8 const loading = queryResult.isLoading;
9
10 if (loading) {
11 return <div>Loading...</div>;
12 } else {
13 return (
14 <div>
15 <input type="text" value={draft} onChange={(e) => setDraft(e.target.value)}></input>
16 </div>
17 );
18 }
19}
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 touseQuery
. Make sure to setrefetchInterval
if you want to enable automatic polling. React query auto sync does not support query data selectors so make sure not to passselect
. 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 touseMutation
. Internally the hook usesonMutate
,onError
, andonSettled
to optimistically update the state but it will call your versions of these functions as well. The hook uses the keypreviousData
to save the previous data in theonMutate
context.autoSaveOptions
: see autoSaveOptionsBelow. If undefined the hook will not automatically save data since it will assume a debounce time ofInfinity
.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 ifrefetchInterval
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 theenabled
parameter ofuseQuery
. IfmutateEnabled
is false and the hook tries to save to the server, a pending save will be created, and whenmutateEnabled
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 useuseState
to create thedraft
value.
useReactQueryAutoSave
Parameters
Same as useReactQueryAutoSync
but does not have queryOptions
.
autoSaveOptions
wait
: number of milliseconds to delay the debounce functionmaxWait
: 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.
1const exampleAtom = atom(undefined);
2
3function Example() {
4 const [draft_, setDraft_] = useAtom(exampleAtom);
5 const { draft, setDraft, queryResult } = useReactQueryAutoSync({
6 queryOptions: { /* omitted */ },
7 mutationOptions: { /* omitted */ },
8 autoSaveOptions: { wait: 1000 },
9 draftProvider: { draft: draft_, setDraft: setDraft_ },
10 });
⚠️ 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
.
1import React from "react";
2import { useReactQueryAutoSync } from "../lib/useReactQueryAutoSync";
3
4// fake api object. You would supply your own!
5const fakeAPI: any = {};
6
7// fake function used to merge server and local state
8const mergeFoo: any = (remote: any, local: any) => ({ ...remote, ...local });
9
10export function Demo() {
11 const { draft, setDraft } = useReactQueryAutoSync({
12 queryOptions: {
13 queryKey: "foo",
14 queryFn: async () => fakeAPI.fetchFoo(),
15 // if you want to poll the server pass a refetchInterval to react query
16 refetchInterval: 5000,
17 },
18 mutationOptions: {
19 mutationFn: async (foo) => fakeAPI.saveFoo(foo),
20 },
21 // pass autoSaveOptions to automatically save to the server with debouncing
22 autoSaveOptions: {
23 wait: 500,
24 },
25 // pass alertIfUnsavedChanges to notify user if they leave with unsaved changes
26 alertIfUnsavedChanges: true,
27 // pass merge to merge server and local state when the server state updates
28 merge: (remoteFoo, localFoo) => mergeFoo(remoteFoo, localFoo),
29 });
30
31 return (
32 <>
33 <input
34 type="text"
35 value={draft.foo}
36 onChange={(e) => {
37 // modify draft with `setDraft` but make sure to modify a copy so you
38 // don't break the ReactQuery caching!
39 setDraft({ ...draft, foo: e.target.value });
40 }}
41 />
42 </>
43 );
44}
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Warn: project license file does not contain an FSF or OSI license.
Reason
Found 1/29 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'main'
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 2 are checked with a SAST tool
Reason
27 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92
- Warn: Project is vulnerable to: GHSA-crh6-fp67-6883
- Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-23wx-cgxq-vpwx
- Warn: Project is vulnerable to: GHSA-f6v4-cf5j-vf3w
- Warn: Project is vulnerable to: GHSA-9pv7-vfvm-6vr7
- Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3
- Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h
- Warn: Project is vulnerable to: GHSA-qrpm-p2h7-hrv2
- Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55
- Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j
- Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j
- Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm
- Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw
- Warn: Project is vulnerable to: GHSA-xrx9-gj26-5wx9
- Warn: Project is vulnerable to: GHSA-353f-5xf4-qw67
- Warn: Project is vulnerable to: GHSA-c24v-8rfc-w8vw
- Warn: Project is vulnerable to: GHSA-8jhw-289h-jh2g
- Warn: Project is vulnerable to: GHSA-64vr-g452-qvp3
- Warn: Project is vulnerable to: GHSA-9cwx-2883-4wfx
- Warn: Project is vulnerable to: GHSA-vg6x-rcgg-rjx6
- Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7
Score
1.7
/10
Last Scanned on 2025-01-27
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More