swr#useSWRConfig TypeScript Examples
The following examples show how to use
swr#useSWRConfig.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: query-data.tsx From plasmic with MIT License | 6 votes |
/**
* Fetches data asynchronously using SWR Hook (https://swr.vercel.app/)
*
* @param key a unique key for this data fetch; if data already exists under this
* key, that data is returned immediately.
* @param fetcher an async function that resolves to the fetched data.
* @param options (optional) an object of options for this hook (https://swr.vercel.app/docs/options).
* @returns an object with either a "data" key with the fetched data if the fetch
* was successful, or an "error" key with the thrown Error if the fetch failed.
*/
export function useMutablePlasmicQueryData<T, E>(
key: Key,
fetcher: Fetcher<T>,
options?: SWRConfiguration<T, E>
) {
const prepassCtx = React.useContext(PrepassContext);
const opts: SWRConfiguration = prepassCtx ? { suspense: true } : {};
const config = useSWRConfig();
React.useEffect(() => {
__SWRConfig = config;
}, [config]);
return useSWR(key, fetcher, { ...options, ...opts });
}
Example #2
Source File: GuestbookEntry.tsx From thvu-blog with MIT License | 5 votes |
export default function GuestbookEntry({ entry, currentUserId }: GuestbookEntryProps) {
const { user, body, updated_at } = entry;
const [isDeleting, setIsDeleting] = useState(false);
const { mutate } = useSWRConfig();
return (
<>
{isDeleting ? (
<LoadingSpinner />
) : (
<div className="flex flex-col space-y-2">
<div className="text-gray-700 max-w-none dark:text-gray-300">{body}</div>
<div className="flex items-center space-x-3">
{user.image ? (
<Image
src={user.image}
alt={user.name}
width={20}
height={20}
className="rounded-full"
/>
) : (
<DefaultAvatar className="w-5 h-5 rounded-full fill-current text-primary-600 dark:text-primary-400" />
)}
<p className="text-sm text-gray-500">{entry.user.name}</p>
<span className=" text-gray-300 dark:text-gray-700">/</span>
<p className="text-sm text-gray-300 dark:text-gray-700">
{format(new Date(updated_at), "d MMM yyyy 'at' h:mm bb")}
</p>
{currentUserId === user.id && (
<>
<span className="text-gray-300 dark:text-gray-700">/</span>
<button
className="text-sm text-danger-600 dark:text-danger-400"
onClick={async (e) => {
e.preventDefault();
setIsDeleting(true);
await fetch(`/api/guestbook/${entry.id}`, {
method: "DELETE",
});
mutate("/api/guestbook");
}}
>
Delete
</button>
</>
)}
</div>
</div>
)}
</>
);
}
Example #3
Source File: Login.tsx From nodestatus with MIT License | 5 votes |
Login: FC = () => {
const navigate = useNavigate();
const { mutate } = useSWRConfig();
const onFinish = useCallback(async (values: { username: string, password: string }) => {
const { username, password } = values;
const res = await axios.post<IResp<string>>('/api/session', { username, password });
const { data } = res;
if (!data.code) {
notify('Success', undefined, 'success');
localStorage.setItem('token', data.data);
mutate('/api/session', { code: 0, msg: 'OK', data: null }, false).then(() => navigate('/dashboard'));
}
}, [navigate, mutate]);
return (
<div
className="flex items-center min-h-screen p-6 bg-violet-50"
style={{ backgroundImage: `url(${loginBackground})` }}
>
<div className="flex-1 h-full max-w-xl md:max-w-4xl mx-auto overflow-hidden bg-white rounded-lg shadow-xl">
<div className="flex flex-col md:flex-row">
<div className="h-60 md:h-auto md:w-1/2">
<img
aria-hidden="true"
className="object-cover w-full h-full"
src={cherry}
alt="Office"
/>
</div>
<div className="flex flex-col items-center justify-center p-6 sm:p-16 md:w-1/2">
<h1 className="text-2xl font-semibold text-gray-700 mb-6">NodeStatus</h1>
<Form
className="w-full"
initialValues={{ remember: true }}
onFinish={onFinish}
>
<Form.Item
name="username"
rules={[{ required: true, message: 'Please input your Username!' }]}
>
<Input size="large" prefix={<UserOutlined />} placeholder="Username" />
</Form.Item>
<Form.Item
name="password"
rules={[{ required: true, message: 'Please input your Password!' }]}
>
<Input
size="large"
prefix={<LockOutlined />}
type="password"
placeholder="Password"
/>
</Form.Item>
<Form.Item>
<Button type="primary" size="large" htmlType="submit" block>
Log in
</Button>
</Form.Item>
</Form>
</div>
</div>
</div>
</div>
);
}
Example #4
Source File: query-data.tsx From plasmic with MIT License | 5 votes |
/**
* Fetches data asynchronously. This data should be considered immutable for the
* session -- there is no way to invalidate or re-fetch this data.
*
* @param key a unique key for this data fetch; if data already exists under this
* key, that data is returned immediately.
* @param fetcher an async function that resolves to the fetched data.
* @returns an object with either a "data" key with the fetched data if the fetch
* was successful, or an "error" key with the thrown Error if the fetch failed.
*/
export function usePlasmicQueryData<T>(
key: Key,
fetcher: Fetcher<T>
): { data?: T; error?: Error; isLoading?: boolean } {
const prepassCtx = React.useContext(PrepassContext);
// @plasmicapp/query is optimized for SSR, so we do not revalidate
// automatically upon hydration; as if the data is immutable.
const opts: SWRConfiguration = {
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
};
if (prepassCtx) {
// If we're doing prepass, then we are always in suspense mode, because
// react-ssr-prepass only works with suspense-throwing data fetching.
opts.suspense = true;
}
const config = useSWRConfig();
React.useEffect(() => {
__SWRConfig = config;
}, [config]);
const resp = useSWR(key, fetcher, opts);
if (resp.data) {
return { data: resp.data };
} else if (resp.error) {
return { error: resp.error };
} else {
return { isLoading: true };
}
}
Example #5
Source File: index.tsx From thvu-blog with MIT License | 4 votes |
export default function Guestbook({ fallbackData }: { fallbackData: GuestBookEntry[] }) {
const [form, setForm] = useState<FormState>(FormState.INITIAL);
const inputEl = useRef<HTMLTextAreaElement>(null);
const { data: session } = useSession();
const { error: entriesError, data: entries } = useSWR<GuestBookEntry[]>(
"/api/guestbook",
fetcher,
{
fallbackData,
}
);
const { mutate } = useSWRConfig();
return (
<>
<LoginView message="Login to sign the guestbook." />
{Boolean(session?.user) && (
<div className="border-2 border-gray-400 dark:border-gray-600 rounded-md p-6 prose dark:prose-dark lg:prose-xl">
<p>Leave a message!</p>
<form
className="w-full my-4"
onSubmit={async (e) => {
e.preventDefault();
setForm(FormState.LOADING);
const res = await fetch("/api/guestbook", {
body: JSON.stringify({
body: inputEl.current?.value,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
});
const { error } = await res.json();
if (error) {
setForm(FormState.ERROR);
return;
}
if (inputEl.current) inputEl.current.value = "";
mutate("/api/guestbook");
setForm(FormState.SUCCESS);
fireConfetti();
}}
>
<textarea
ref={inputEl}
aria-label="Your message"
placeholder="Your message..."
required
style={{ resize: "none" }}
className="px-4 py-2 my-4 focus:ring-primary-500 focus:border-primary-500 block w-full border-gray-300 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
/>
<Button type="submit">
{form === FormState.LOADING ? <LoadingSpinner /> : "Sign"}
</Button>
</form>
{form === FormState.ERROR && <ErrorMessage>An error occurred.</ErrorMessage>}
{form === FormState.SUCCESS && (
<SuccessMessage>Awesome! Thank you for signing my guestbook.</SuccessMessage>
)}
</div>
)}
<div className="mt-4 space-y-8">
{entriesError && (
<ErrorMessage>
An unexpected error occurred. The entries are not available for now. Please try again
later
</ErrorMessage>
)}
{entries ? (
entries.map((entry) => (
<GuestbookEntry key={entry.id} entry={entry} currentUserId={session?.id as string} />
))
) : (
<LoadingSpinner />
)}
</div>
</>
);
}
Example #6
Source File: Badge.tsx From thvu-blog with MIT License | 4 votes |
export default function Badge({ skill, user, currentUserId }: Props) {
const [state, setState] = useState<FormState>(FormState.INITIAL);
const { mutate } = useSWRConfig();
async function onEndorse(skillId: string) {
setState(FormState.LOADING);
const res = await fetch("/api/endorsement", {
body: JSON.stringify({
skillId,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
});
const { error } = await res.json();
if (error) {
setState(FormState.ERROR);
return;
}
mutate("/api/skill-category");
setState(FormState.SUCCESS);
fireConfetti();
}
const isUserEndorsed = skill?.users?.find((u) => u.id === currentUserId);
return (
<div className="space-y-4">
<div className="flex items-center text-base font-semibold">
{state === FormState.LOADING ? (
<div className="flex items-center justify-center w-8 h-8">
<LoadingSpinner />
</div>
) : isUserEndorsed ? (
<button
className="font-semibold disabled:hover:cursor-not-allowed text-success-700 dark:text-success-400"
title="You already endorsed this skill!"
disabled
>
<DoneIcon className="inline w-8 h-8 fill-current " />
</button>
) : (
<button
className="font-semibold disabled:hover:cursor-not-allowed text-primary-600 dark:text-primary-400 hover:text-gray-700 dark:hover:text-gray-300 disabled:text-gray-700 dark:disabled:text-gray-300 "
disabled={!Boolean(user)}
title={!Boolean(user) ? "Please login first." : "Endorse this skill!"}
onClick={() => onEndorse(skill.id)}
>
<ButtonIcon className="inline w-8 h-8 fill-current " />
</button>
)}
<span className="ml-2">{skill.name}</span>
</div>
<div className="flex items-center gap-1 flex-wrap">
{skill.users.map((user) => (
<span title={user.name} key={user.id} className="w-8 h-8">
{user.image ? (
<Image
src={user.image}
alt={user.name}
width={32}
height={32}
className="rounded-full"
/>
) : (
<DefaultAvatar className="w-8 h-8 p-0.5 rounded-full fill-current text-primary-600 dark:text-primary-400 border-2 border-solid border-primary-600 dark:border-primary-400" />
)}
</span>
))}
</div>
{skill.users.length > 0 && (
<p className="text-sm text-gray-600 dark:text-gray-400">
<strong className="text-black dark:text-white">{skill.users.length}</strong>{" "}
{`${skill.name} endorsement${skill.users.length > 1 ? "s" : ""} from:`}
<span className="mx-2">{skill.users.map((u) => u.name).join(", ")}</span>
</p>
)}
{state === FormState.ERROR && <ErrorMessage>An unexpected error occurred.</ErrorMessage>}
{state === FormState.SUCCESS && (
<SuccessMessage>Thank you for your endorsement!</SuccessMessage>
)}
</div>
);
}
Example #7
Source File: useEtherSWR.ts From ether-swr with MIT License | 4 votes |
function useEtherSWR<Data = any, Error = any>(
...args: any[]
): SWRResponse<Data, Error> {
let _key: ethKeyInterface
let fn: any //fetcherFn<Data> | undefined
let config: EthSWRConfigInterface<Data, Error> = { subscribe: [] }
let isMulticall = false
if (args.length >= 1) {
_key = args[0]
isMulticall = Array.isArray(_key[0])
}
if (args.length > 2) {
fn = args[1]
//FIXME we lost default value subscriber = []
config = args[2]
} else {
if (typeof args[1] === 'function') {
fn = args[1]
} else if (typeof args[1] === 'object') {
config = args[1]
}
}
config = Object.assign({}, useContext(EthSWRConfigContext), config)
if (fn === undefined) {
fn = config.fetcher || etherJsFetcher(config.web3Provider, config.ABIs)
}
// TODO LS implement a getTarget and change subscribe interface {subscribe: {name: "Transfer", target: 0x01}}
const [target] = isMulticall
? [_key[0][0]] // pick the first element of the list.
: _key
const { cache } = useSWRConfig()
// we need to serialize the key as string otherwise
// a new array is created everytime the component is rendered
// we follow SWR format
const normalizeKey = isMulticall ? JSON.stringify(_key) : _key
// base methods (e.g. getBalance, getBlockNumber, etc)
useEffect(() => {
if (!config.web3Provider || !config.subscribe || Array.isArray(target)) {
// console.log('skip')
return () => ({})
}
// console.log('effect!')
const contract = buildContract(target, config)
const subscribers = Array.isArray(config.subscribe)
? config.subscribe
: [config.subscribe]
const instance: Contract | Provider = contract || config.web3Provider
subscribers.forEach(subscribe => {
let filter
const internalKey = unstable_serialize(normalizeKey)
if (typeof subscribe === 'string') {
filter = subscribe
instance.on(filter, () => {
// console.log('on(string):', { filter }, Array.from(cache.keys()))
mutate(internalKey, undefined, true)
})
} else if (typeof subscribe === 'object' && !Array.isArray(subscribe)) {
const { name, topics, on } = subscribe
const args = topics || []
filter = contract ? contract.filters[name](...args) : name
// console.log('subscribe:', filter)
instance.on(filter, (...args) => {
if (on) {
// console.log('on(object):', { filter }, Array.from(cache.keys()))
on(cache.get(internalKey), ...args)
} else {
// auto refresh
// console.log('auto(refresh):', { filter }, Array.from(cache.keys()))
mutate(internalKey, undefined, true)
}
})
}
})
return () => {
subscribers.forEach(filter => {
instance.removeAllListeners(filter)
})
}
}, [unstable_serialize(normalizeKey), target])
return useSWR(normalizeKey, fn, config)
}