package.mutation.dist.index.mjs Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swr Show documentation
Show all versions of swr Show documentation
React Hooks library for remote data fetching
import { useRef, useCallback } from 'react';
import useSWR, { useSWRConfig } from 'swr';
import { withMiddleware, useStateWithDeps, UNDEFINED, serialize, mergeObjects, getTimestamp, useIsomorphicLayoutEffect } from 'swr/_internal';
const mutation = ()=>{
return (key, fetcher, config = {})=>{
const { mutate } = useSWRConfig();
const keyRef = useRef(key);
const fetcherRef = useRef(fetcher);
const configRef = useRef(config);
// Ditch all mutation results that happened earlier than this timestamp.
const ditchMutationsUntilRef = useRef(0);
const [stateRef, stateDependencies, setState] = useStateWithDeps({
data: UNDEFINED,
error: UNDEFINED,
isMutating: false
});
const currentState = stateRef.current;
const trigger = useCallback(async (arg, opts)=>{
const [serializedKey, resolvedKey] = serialize(keyRef.current);
if (!fetcherRef.current) {
throw new Error('Can’t trigger the mutation: missing fetcher.');
}
if (!serializedKey) {
throw new Error('Can’t trigger the mutation: missing key.');
}
// Disable cache population by default.
const options = mergeObjects(mergeObjects({
populateCache: false,
throwOnError: true
}, configRef.current), opts);
// Trigger a mutation, and also track the timestamp. Any mutation that happened
// earlier this timestamp should be ignored.
const mutationStartedAt = getTimestamp();
ditchMutationsUntilRef.current = mutationStartedAt;
setState({
isMutating: true
});
try {
const data = await mutate(serializedKey, fetcherRef.current(resolvedKey, {
arg
}), // We must throw the error here so we can catch and update the states.
mergeObjects(options, {
throwOnError: true
}));
// If it's reset after the mutation, we don't broadcast any state change.
if (ditchMutationsUntilRef.current <= mutationStartedAt) {
setState({
data,
isMutating: false,
error: undefined
});
options.onSuccess == null ? void 0 : options.onSuccess(data, serializedKey, options);
}
return data;
} catch (error) {
// If it's reset after the mutation, we don't broadcast any state change
// or throw because it's discarded.
if (ditchMutationsUntilRef.current <= mutationStartedAt) {
setState({
error: error,
isMutating: false
});
options.onError == null ? void 0 : options.onError(error, serializedKey, options);
if (options.throwOnError) {
throw error;
}
}
}
}, // eslint-disable-next-line react-hooks/exhaustive-deps
[]);
const reset = useCallback(()=>{
ditchMutationsUntilRef.current = getTimestamp();
setState({
data: UNDEFINED,
error: UNDEFINED,
isMutating: false
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useIsomorphicLayoutEffect(()=>{
keyRef.current = key;
fetcherRef.current = fetcher;
configRef.current = config;
});
// We don't return `mutate` here as it can be pretty confusing (e.g. people
// calling `mutate` but they actually mean `trigger`).
// And also, `mutate` relies on the useSWR hook to exist too.
return {
trigger,
reset,
get data () {
stateDependencies.data = true;
return currentState.data;
},
get error () {
stateDependencies.error = true;
return currentState.error;
},
get isMutating () {
stateDependencies.isMutating = true;
return currentState.isMutating;
}
};
};
};
/**
* A hook to define and manually trigger remote mutations like POST, PUT, DELETE and PATCH use cases.
*
* @link https://swr.vercel.app/docs/mutation
* @example
* ```jsx
* import useSWRMutation from 'swr/mutation'
*
* const {
* data,
* error,
* trigger,
* reset,
* isMutating
* } = useSWRMutation(key, fetcher, options?)
* ```
*/ var index = withMiddleware(useSWR, mutation);
export { index as default };