~repos /website

#astro#js#html#css

git clone https://pyrossh.dev/repos/website.git

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


40432abc pyrossh

1 year ago
add new post
src/lib/dateUtils.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export const formatDate = (d) =>
2
- new Intl.DateTimeFormat('en-IN').format(new Date(d)).replaceAll('/', '-');
2
+ new Intl.DateTimeFormat('en-GB').format(new Date(d)).replaceAll('/', '-');
3
3
 
4
4
  export const formatDateLong = (d) =>
5
- new Intl.DateTimeFormat('en-IN', { dateStyle: 'long' }).format(new Date(d));
5
+ new Intl.DateTimeFormat('en-GB', { dateStyle: 'long' }).format(new Date(d));
src/posts/react-powertools-swr.md ADDED
@@ -0,0 +1,210 @@
1
+ ---
2
+ title: 'React Powertools: SWR'
3
+ description: A react library that makes it easier to fetch data
4
+ image: /images/gopibot.png
5
+ date: 2024-08-16
6
+ tags:
7
+ - react
8
+ - frontend
9
+ - hooks
10
+ - swr
11
+ - fetch
12
+ published: true
13
+ ---
14
+
15
+ The **SWR** library provides hooks which help in facilitating fetching and revalidating data so that the UI will be always fast and reactive. It uses the stale-while-revalidate, a HTTP cache invalidation strategy, to first return the data from cache (stale), then send the fetch request (revalidate), and finally come with the up-to-date data.
16
+
17
+ You can install it using this command: `npm i swr`
18
+
19
+ ### useSWR
20
+
21
+ This hook exposes few options to customise the fetching/revalidation logic,
22
+
23
+ ```tsx
24
+ const { data, error, isLoading, isValidating, mutate } = useSWR(key, fetcher, options);
25
+ ```
26
+
27
+ **Parameters**
28
+
29
+ - `key`: a unique key string for the request
30
+ - `fetcher`: a Promise-returning function to fetch your data
31
+ - `options`: an object of options for this SWR hook
32
+
33
+ **Return values**
34
+
35
+ - `data`: data for the given key resolved by `fetcher`
36
+ - `error`: error thrown by `fetcher`
37
+ - `isLoading`: if there's an ongoing request and no "loaded data" or state data
38
+ - `isValidating`: if there's a revalidation request happening
39
+ - `mutate(data?, options?)`: function to mutate the cached data
40
+
41
+ > Before SWR
42
+
43
+ ```tsx
44
+ import { useState, useEffect } from 'react';
45
+
46
+ const useUser = (id: string) => {
47
+ const [user, setUser] = useState(null);
48
+ const [loading, setLoading] = useState(false);
49
+ const [error, setError] = useState(null);
50
+
51
+ useEffect(() => {
52
+ setLoading(true);
53
+ setError(null);
54
+ fetch(`/users/${id}`)
55
+ .then((res) => res.json())
56
+ .then((data) => {
57
+ setUser(data);
58
+ setLoading(false);
59
+ })
60
+ .catch((err) => {
61
+ setError(err);
62
+ setLoading(false);
63
+ });
64
+ }, [id]);
65
+ return {
66
+ user,
67
+ loading,
68
+ error,
69
+ };
70
+ };
71
+ ```
72
+
73
+ > After SWR
74
+
75
+ ```tsx
76
+ import useSWR from 'swr';
77
+
78
+ const fetcher = (...args) => fetch(...args).then((res) => res.json());
79
+
80
+ const useUser = (id: string) => {
81
+ const { data, error, isLoading } = useSWR(`/users/${id}`, fetcher);
82
+ return {
83
+ user: data,
84
+ isLoading,
85
+ error: error,
86
+ };
87
+ };
88
+ ```
89
+
90
+ ### Configuration
91
+
92
+ You can configure a global fetcher function so that you don't need pass the fetcher on every hook call using the `SWRConfig` Provider at the root app level. The library uses a global cache to store and share data across all components, you can also customise this behaviour with the `provider` option.
93
+
94
+ ```tsx
95
+ import { SWRConfig } from 'swr';
96
+
97
+ const fetcher = (...args) => fetch(...args).then((res) => res.json());
98
+
99
+ function App() {
100
+ return (
101
+ <SWRConfig value={{ fetcher: fetcher, provider: () => new Map() }}>
102
+ <Page />
103
+ </SWRConfig>
104
+ );
105
+ }
106
+ ```
107
+
108
+ ### Automatic Revalidation
109
+
110
+ You can use the options parameter in the API to configure automatic revalidation of your components based on different criteria. This can be done at a global level using SWRConfig provider or at a local hook level using the options parameter.
111
+
112
+ - `revalidateIfStale`: automatically revalidate even if there is stale data
113
+ - `revalidateOnMount`: enable or disable automatic revalidation when component is mounted
114
+ - `revalidateOnFocus`: automatically revalidate when window gets focused
115
+ - `revalidateOnReconnect`: automatically revalidate when the browser regains a network connection
116
+ - `refreshInterval`:  automatically revalidate every interval in milliseconds
117
+
118
+ There are many more options apart from these.
119
+
120
+ ### Manual Revalidation
121
+
122
+ There are 2 ways to trigger a revalidation request manually,
123
+
124
+ **1.** You can use the **mutate** function returned by the **useSWR** hook to trigger a revalidation of the data
125
+
126
+ ```tsx
127
+ import useSWR from 'swr';
128
+
129
+ const Profile = () => {
130
+ const { data, error, isLoading, mutate } = useSWR(`/users/1`);
131
+ if (error) return <div>failed to load</div>;
132
+ if (isLoading) return <div className="text">loading...</div>;
133
+ return (
134
+ <div>
135
+ <div>{JSON.stringify(data, null, 2)}</div>
136
+ <button onClick={() => mutate()}>Update User</button>
137
+ </div>
138
+ );
139
+ };
140
+ ```
141
+
142
+ This can be used to implement optimistic updates as well if you know what data needs to change and once the revalidation is complete the cache gets updated with new data from the server.
143
+
144
+ ```tsx
145
+ mutate({ ...data, name: 'John Doe' });
146
+ ```
147
+
148
+ **2.** If you need to update the cache from another component which doesn't have access to the **useSWR** hook you can use the **mutate** function returned by the **useSWRConfig** to get access to the cache. Here you would need to provide the key to trigger a revalidation of the request.
149
+
150
+ ```tsx
151
+ import { useSWRConfig } from 'swr';
152
+ // or import { mutate } from "swr"
153
+
154
+ const UpdateButton = () => {
155
+ const { mutate } = useSWRConfig();
156
+ return (
157
+ <div>
158
+ <button onClick={() => mutate(`/users/1`)}>Update User</button>
159
+ </div>
160
+ );
161
+ };
162
+ ```
163
+
164
+ Here as well you can do optimistic updates similarly,
165
+
166
+ ```tsx
167
+ mutate(`/users/1`, { ...data, name: 'John Doe' });
168
+ ```
169
+
170
+ ### **useSWRMutation**
171
+
172
+ This hook makes it easier to handle update requests and provides necessary state
173
+
174
+ ```tsx
175
+ import useSWRMutation from 'swr/mutation';
176
+
177
+ async function updateUser(url, data) {
178
+ await fetch(url, {
179
+ method: 'POST',
180
+ body: JSON.stringify(data),
181
+ });
182
+ }
183
+
184
+ function Profile() {
185
+ const { data, error, isMutating, trigger } = useSWRMutation(
186
+ '/api/user/update',
187
+ updateUser,
188
+ options,
189
+ );
190
+ return (
191
+ <button onClick={() => trigger({ name: 'John Doe' })}>
192
+ {isMutating ? 'Updating...' : 'Update User'}
193
+ </button>
194
+ );
195
+ }
196
+ ```
197
+
198
+ **Parameters**
199
+
200
+ - `key`: a unique key string for the request
201
+ - `fetcher(key, { arg })`: an async function for remote mutation
202
+ - `options`: an optional object to configure revalidation and optimistic updates
203
+
204
+ **Return values**
205
+
206
+ - `data`: data for the given key returned from the update request
207
+ - `error`: error thrown by the request
208
+ - `trigger(arg, options)`: a function to trigger a remote mutation
209
+ - `reset`: a function to reset the state
210
+ - `isMutating`: if there's an ongoing update request
svelte.config.js CHANGED
@@ -11,7 +11,7 @@ const mdsvexOptions = {
11
11
  [
12
12
  github,
13
13
  {
14
- repository: 'https://github.com/pyrossh/pyros.sh',
14
+ repository: 'https://github.com/pyrossh/pyrossh.dev',
15
15
  },
16
16
  ],
17
17
  ],
@@ -19,7 +19,7 @@ const mdsvexOptions = {
19
19
  highlighter: async (code, lang = 'text') => {
20
20
  const highlighter = await getHighlighter({
21
21
  themes: ['dracula'],
22
- langs: ['javascript', 'typescript', 'go'],
22
+ langs: ['javascript', 'typescript', 'go', 'shell', 'tsx'],
23
23
  });
24
24
  await highlighter.loadLanguage('javascript', 'typescript', 'go');
25
25
  const html = escapeSvelte(highlighter.codeToHtml(code, { lang, theme: 'dracula' }));
tailwind.config.js CHANGED
@@ -20,12 +20,41 @@ export default {
20
20
  h2: {
21
21
  color: theme('colors.black'),
22
22
  },
23
+ h3: {
24
+ color: theme('colors.black'),
25
+ },
23
26
  pre: {
24
27
  padding: '16px',
25
28
  borderRadius: '16px',
26
29
  fontSize: '0.8rem',
27
30
  fontFamily: 'monospace',
28
31
  },
32
+ 'code::before': {
33
+ content: '&nbsp;&nbsp;',
34
+ },
35
+ 'code::after': {
36
+ content: '&nbsp;&nbsp;',
37
+ },
38
+ code: {
39
+ color: '#d14',
40
+ background: '#f6f6f6',
41
+ border: '1px solid #e1e1e8',
42
+ wordWrap: 'break-word',
43
+ boxDecorationBreak: 'clone',
44
+ padding: '2px 4px',
45
+ borderRadius: '.2rem',
46
+ fontWeight: 400,
47
+ fontSize: '0.8rem',
48
+ },
49
+ blockquote: {
50
+ background: '#f8ffaa',
51
+ fontWeight: 600,
52
+ fontStyle: 'normal',
53
+ padding: '0.4rem',
54
+ },
55
+ 'blockquote p:first-of-type': { margin: 0 },
56
+ 'blockquote p:first-of-type::before': { content: 'none' },
57
+ 'blockquote p:first-of-type::after': { content: 'none' },
29
58
  '--tw-prose-body': theme('colors.black'),
30
59
  '--tw-prose-headings': theme('colors.gray[100]'),
31
60
  '--tw-prose-lead': theme('colors.black'),