feat : approach 1

This commit is contained in:
Dishank-Kheni 2024-05-26 22:50:32 +02:00
parent e8e3cc70ab
commit 93e90eaf3f
9 changed files with 323 additions and 109 deletions

35
App.js
View File

@ -93,29 +93,22 @@
// </View>
// </QueryClientProvider>
//);
//
//export default App;
import React from 'react'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { persister, queryClient } from './src/queryClient'
import OrderComponent from './src/OrderComponent'
import {ToastAndroid} from 'react-native';
// App.js
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import MyComponent from './src/MyComponent';
function App() {
const queryClient = new QueryClient();
const App = () => {
return (
<PersistQueryClientProvider
client={queryClient}
persistOptions={{ persister }}
onSuccess={() => {
queryClient.resumePausedMutations().then(() => {
queryClient.invalidateQueries()
})
}}
>
<OrderComponent />
</PersistQueryClientProvider>
)
}
<QueryClientProvider client={queryClient}>
<MyComponent />
</QueryClientProvider>
);
};
export default App
export default App;

217
package-lock.json generated
View File

@ -10,13 +10,17 @@
"dependencies": {
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-community/netinfo": "^11.3.2",
"@reduxjs/toolkit": "^2.2.5",
"@tanstack/query-async-storage-persister": "^5.37.1",
"@tanstack/query-sync-storage-persister": "^5.37.1",
"@tanstack/react-query": "^5.37.1",
"@tanstack/react-query": "^5.39.0",
"@tanstack/react-query-persist-client": "^5.37.1",
"axios": "^1.6.8",
"react": "18.2.0",
"react-native": "0.74.1"
"react-native": "0.74.1",
"react-query": "^3.39.3",
"react-redux": "^9.1.2",
"redux-persist": "^6.0.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
@ -4312,6 +4316,29 @@
}
}
},
"node_modules/@reduxjs/toolkit": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.5.tgz",
"integrity": "sha512-aeFA/s5NCG7NoJe/MhmwREJxRkDs0ZaSqt0MxhWUrwCf1UQXpwR87RROJEql0uAkLI6U7snBOYOcKw83ew3FPg==",
"dependencies": {
"immer": "^10.0.3",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
"reselect": "^5.1.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@rnx-kit/chromium-edge-launcher": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz",
@ -4444,11 +4471,11 @@
}
},
"node_modules/@tanstack/react-query": {
"version": "5.37.1",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.37.1.tgz",
"integrity": "sha512-EhtBNA8GL3XFeSx6VYUjXQ96n44xe3JGKZCzBINrCYlxbZP6UwBafv7ti4eSRWc2Fy+fybQre0w17gR6lMzULA==",
"version": "5.39.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.39.0.tgz",
"integrity": "sha512-zc0WnyEffyTgG+myLv8cY2tJOUT6jOprCiprpbMqylCaCFipSDUPCYCt2AC+qxgk2CFuqiI/fjb1u5/HhLkrPg==",
"dependencies": {
"@tanstack/query-core": "5.36.1"
"@tanstack/query-core": "5.38.0"
},
"funding": {
"type": "github",
@ -4474,6 +4501,15 @@
"react": "^18.0.0"
}
},
"node_modules/@tanstack/react-query/node_modules/@tanstack/query-core": {
"version": "5.38.0",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.38.0.tgz",
"integrity": "sha512-QtkoxvFcu52mNpp3+qOo9H265m3rt83Dgbw5WnNyJvr83cegrQ7zT8haHhL4Rul6ZQkeovxyWbXVW9zI0WYx6g==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@ -4603,6 +4639,11 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/yargs": {
"version": "17.0.32",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
@ -5456,6 +5497,14 @@
}
]
},
"node_modules/big-integer": {
"version": "1.6.52",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
"integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@ -5486,6 +5535,21 @@
"node": ">=8"
}
},
"node_modules/broadcast-channel": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz",
"integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==",
"dependencies": {
"@babel/runtime": "^7.7.2",
"detect-node": "^2.1.0",
"js-sha3": "0.8.0",
"microseconds": "0.2.0",
"nano-time": "1.0.0",
"oblivious-set": "1.0.0",
"rimraf": "3.0.2",
"unload": "2.2.0"
}
},
"node_modules/browserslist": {
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
@ -6278,6 +6342,11 @@
"node": ">=8"
}
},
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="
},
"node_modules/diff-sequences": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
@ -8128,6 +8197,15 @@
"node": ">=16.x"
}
},
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -10321,6 +10399,11 @@
"@sideway/pinpoint": "^2.0.0"
}
},
"node_modules/js-sha3": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -10877,6 +10960,15 @@
"resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz",
"integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q=="
},
"node_modules/match-sorter": {
"version": "6.3.4",
"resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz",
"integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==",
"dependencies": {
"@babel/runtime": "^7.23.8",
"remove-accents": "0.5.0"
}
},
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
@ -11308,6 +11400,11 @@
"node": ">=8.6"
}
},
"node_modules/microseconds": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz",
"integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA=="
},
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
@ -11385,6 +11482,14 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/nano-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz",
"integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==",
"dependencies": {
"big-integer": "^1.6.16"
}
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@ -11639,6 +11744,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/oblivious-set": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz",
"integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw=="
},
"node_modules/on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@ -12357,6 +12467,53 @@
"async-limiter": "~1.0.0"
}
},
"node_modules/react-query": {
"version": "3.39.3",
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz",
"integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"broadcast-channel": "^3.4.1",
"match-sorter": "^6.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-redux": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
"dependencies": {
"@types/use-sync-external-store": "^0.0.3",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^18.2.25",
"react": "^18.0",
"redux": "^5.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-refresh": {
"version": "0.14.2",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
@ -12432,6 +12589,27 @@
"node": ">= 4"
}
},
"node_modules/redux": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
},
"node_modules/redux-persist": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz",
"integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==",
"peerDependencies": {
"redux": ">4.0.0"
}
},
"node_modules/redux-thunk": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
"peerDependencies": {
"redux": "^5.0.0"
}
},
"node_modules/reflect.getprototypeof": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
@ -12535,6 +12713,11 @@
"jsesc": "bin/jsesc"
}
},
"node_modules/remove-accents": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz",
"integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A=="
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@ -12548,6 +12731,11 @@
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"node_modules/reselect": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.0.tgz",
"integrity": "sha512-aw7jcGLDpSgNDyWBQLv2cedml85qd95/iszJjN988zX1t7AVRJi19d9kto5+W7oCfQ94gyo40dVbT6g2k4/kXg=="
},
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@ -13630,6 +13818,15 @@
"node": ">= 4.0.0"
}
},
"node_modules/unload": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz",
"integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==",
"dependencies": {
"@babel/runtime": "^7.6.2",
"detect-node": "^2.0.4"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@ -13676,6 +13873,14 @@
"punycode": "^2.1.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

View File

@ -12,13 +12,17 @@
"dependencies": {
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-community/netinfo": "^11.3.2",
"@reduxjs/toolkit": "^2.2.5",
"@tanstack/query-async-storage-persister": "^5.37.1",
"@tanstack/query-sync-storage-persister": "^5.37.1",
"@tanstack/react-query": "^5.37.1",
"@tanstack/react-query": "^5.39.0",
"@tanstack/react-query-persist-client": "^5.37.1",
"axios": "^1.6.8",
"react": "18.2.0",
"react-native": "0.74.1"
"react-native": "0.74.1",
"react-query": "^3.39.3",
"react-redux": "^9.1.2",
"redux-persist": "^6.0.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",

47
src/MyComponent.js Normal file
View File

@ -0,0 +1,47 @@
// MyComponent.js
import React, { useEffect } from 'react';
import { Button, View, Text } from 'react-native';
import NetInfo from '@react-native-community/netinfo';
import AsyncStorage from '@react-native-async-storage/async-storage';
import useOfflineMutation from './useOfflineMutation';
const retryOfflineRequests = async (mutation) => {
const pendingRequest = await AsyncStorage.getItem('pendingRequest');
if (pendingRequest) {
mutation.mutate(JSON.parse(pendingRequest));
}
};
const MyComponent = () => {
const mutation = useOfflineMutation();
// Retry pending requests on component mount
useEffect(() => {
retryOfflineRequests(mutation);
// Add event listener for when the app comes back online
const unsubscribe = NetInfo.addEventListener(state => {
if (state.isConnected) {
retryOfflineRequests(mutation);
}
});
return () => {
unsubscribe();
};
}, [mutation]);
const handleSubmit = (data) => {
mutation.mutate(data);
};
return (
<View>
<Button onPress={() => handleSubmit({ title: 'New Todo' })} title="Add Todo" />
{mutation.isLoading && <Text>Loading...</Text>}
{mutation.isError && <Text>Error: {mutation.error.message}</Text>}
</View>
);
};
export default MyComponent;

View File

@ -1,26 +0,0 @@
import React, {useState} from 'react';
import {ToastAndroid, Text, View, Button} from 'react-native';
import {useMutation} from '@tanstack/react-query';
function OrderComponent() {
const mutation = useMutation(['placeOrder']);
const [orderData, setOrderData] = useState({title: '', body: '', userId: 1});
const handlePlaceOrder = id => {
mutation.mutate({title: '', body: '', userId: id});
};
return (
<View>
<Text>Place Order</Text>
<Button
title="Make order"
onPress={handlePlaceOrder(Math.floor(Math.random() * 100))}
/>
{mutation.isError && <Text>Error: {mutation.error.message}</Text>}
{mutation.data && <Text>Order ID: {mutation.data.id}</Text>}
</View>
);
}
export default OrderComponent;

15
src/api.js Normal file
View File

@ -0,0 +1,15 @@
// api.js
export const sendRequest = async (data) => {
const response = await fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
};

View File

@ -1,49 +0,0 @@
import { QueryClient, MutationCache } from '@tanstack/react-query';
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {ToastAndroid} from 'react-native';
// Create a persister using localStorrage
const persister = createAsyncStoragePersister({
storage: AsyncStorage,
})
// Create a QueryClient instance
const queryClient = new QueryClient({
defaultOptions: {
mutations: {
retry: true, // Retry indefinitely
},
queries: {
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
mutationCache: new MutationCache({
onSuccess: (data) => {
ToastAndroid.show('Order placed successfully',ToastAndroid.SHORT)
},
onError: (error) => {
ToastAndroid.show('Order placement failed, retrying...',ToastAndroid.SHORT)
},
}),
})
// Set default mutation function to handle orders
queryClient.setMutationDefaults(['placeOrder'], {
mutationFn: async (orderData) => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(orderData),
})
if (!response.ok) {
throw new Error('Order placement failed')
}
return response.json()
},
retry: true, // Retry indefinitely until it succeeds
})
export { persister, queryClient }

30
src/useOfflineMutation.js Normal file
View File

@ -0,0 +1,30 @@
// useOfflineMutation.js
import { useMutation, useQueryClient } from '@tanstack/react-query';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { sendRequest } from './api';
const useOfflineMutation = () => {
const queryClient = useQueryClient();
const mutation = useMutation(sendRequest, {
onMutate: async (newData) => {
await queryClient.cancelQueries('data');
// Persist the request in AsyncStorage
await AsyncStorage.setItem('pendingRequest', JSON.stringify(newData));
},
onError: (error, newData) => {
console.error('Failed to send request:', error);
// Keep the request in AsyncStorage for retry
},
onSuccess: async () => {
// Remove the request from AsyncStorage
await AsyncStorage.removeItem('pendingRequest');
queryClient.invalidateQueries('data');
},
});
return mutation;
};
export default useOfflineMutation;

View File

@ -1,5 +0,0 @@
import { useMutation } from '@tanstack/react-query'
export function usePlaceOrder() {
return useMutation(['placeOrder']);
}