deno.land / x / jotai@v1.8.4 / examples / hacker_news / src / App.tsx

نووسراو ببینە
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { Suspense } from 'react'import { a, useSpring } from '@react-spring/web'import Parser from 'html-react-parser'import { Provider, atom, useAtom, useSetAtom } from 'jotai'
type PostData = { by: string descendants?: number id: number kids?: number[] parent: number score?: number text?: string time: number title?: string type: 'comment' | 'story' url?: string}
const postId = atom(9001)const postData = atom(async (get) => { const id = get(postId) const response = await fetch( `https://hacker-news.firebaseio.com/v0/item/${id}.json` ) const data: PostData = await response.json() return data})
function Id() { const [id] = useAtom(postId) const props = useSpring({ from: { id }, id, reset: true }) return <a.h1>{props.id.to(Math.round)}</a.h1>}
function Next() { // Use `useSetAtom` to avoid re-render // const [, set] = useAtom(postId) const setPostId = useSetAtom(postId) return ( <button onClick={() => setPostId((id) => id + 1)}> <div></div> </button> )}
function PostTitle() { const [{ by, text, time, title, url }] = useAtom(postData) return ( <> <h2>{by}</h2> <h6>{new Date(time * 1000).toLocaleDateString('en-US')}</h6> {title && <h4>{title}</h4>} {url && <a href={url}>{url}</a>} {text && <div>{Parser(text)}</div>} </> )}
export default function App() { return ( <Provider> <Id /> <div> <Suspense fallback={<h2>Loading...</h2>}> <PostTitle /> </Suspense> </div> <Next /> </Provider> )}
jotai

Version Info

Tagged at
2 years ago