Getting Started
- foo
- bar
- baz
- qux
- qwe
- he
- be
- wo
- be da
- da
- ba
111 111
222 222
333 333
Development
html {
background: red;
}
type Character {
name: String
}
# type Character {
class Character:
# name: String
def name(self):
return self._name
// type Character {
public class Character {
// name: String
public String Name { get; }
}
__esModule
Docs theme box-decoration-theme: clone can create confusing output over line breaks
Link
Foo "I am from export const"
Bar code
Latex
Da
MaChina
Qux someVal
My file is <MyFile />
Inside your React project directory, run the following:
npm i swr __esModule
Quick Start
For normal RESTful APIs with JSON data, first you need to create a fetcher
function, which is just a wrapper of the native fetch
:
const fetcher = (...args) => fetch(...args).then(res => res.json())
If you want to use GraphQL API or libs like Axios, you can create your own fetcher function. Check here for more examples.
- schema.graphql
- schema.graphql
- schema.graphql
- schema.graphql
Renders properly
Renders on next line
Then you can import useSWR
and start using it inside any function components:
import useSWR from 'swr'
function Profile() {
const { data, error } = useSWR('/api/user/123', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
// render data
return <div>hello {data.name}!</div>
}
Normally, there’re 3 possible states of a request: “loading”, “ready”, or
“error”. You can use the value of data
and error
to determine the current
state of the request, and return the corresponding UI.
Make It Reusable
Here’s a JavaScript expression: const a = 1 + 2
.
When building a web app, you might need to reuse the data in many places of the UI. It is incredibly easy to create reusable data hooks on top of SWR:
function useUser(id) {
const { data, error } = useSWR(`/api/user/${id}`, fetcher)
return {
user: data,
isLoading: !error && !data,
isError: error
}
}
And use it in your components:
function Avatar({ id }) {
const { user, isLoading, isError } = useUser(id)
if (isLoading) return <Spinner />
if (isError) return <Error />
return <img src={user.avatar} />
}
By adopting this pattern, you can forget about fetching data in the imperative way: start the request, update the loading state, and return the final result. Instead, your code is more declarative: you just need to specify what data is used by the component.
Example
In a real-world example, our website shows a navbar and the content, both depend
on user
:
Traditionally, we fetch data once using useEffect
in the top level component,
and pass it to child components via props (notice that we don’t handle error
state for now):
// page component
function Page() {
const [user, setUser] = useState(null)
// fetch data
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data))
}, [])
// global loading state
if (!user) return <Spinner />
return (
<div>
<Navbar user={user} />
<Content user={user} />
</div>
)
}
// child components
function Navbar({ user }) {
return (
<div>
...
<Avatar user={user} />
</div>
)
}
function Content({ user }) {
return <h1>Welcome back, {user.name}</h1>
}
function Avatar({ user }) {
return <img src={user.avatar} alt={user.name} />
}
Usually, we need to keep all the data fetching in the top level component and add props to every component deep down the tree. The code will become harder to maintain if we add more data dependency to the page.
Although we can avoid passing props using Context, there’s still the dynamic content problem: components inside the page content can be dynamic, and the top level component might not know what data will be needed by its child components.
SWR solves the problem perfectly. With the useUser
hook we just created, the
code can be refactored to:
// page component
function Page() {
return (
<div>
<Navbar />
<Content />
</div>
)
}
// child components
function Navbar() {
return (
<div>
...
<Avatar />
</div>
)
}
function Content() {
const { user, isLoading } = useUser()
if (isLoading) return <Spinner />
return <h1>Welcome back, {user.name}</h1>
}
function Avatar() {
const { user, isLoading } = useUser()
if (isLoading) return <Spinner />
return <img src={user.avatar} alt={user.name} />
}
Data is now bound to the components which need the data, and all components are independent to each other. All the parent components don’t need to know anything about the data or passing data around. They just render. The code is much simpler and easier to maintain now.
The most beautiful thing is that there will be only 1 request sent to the API, because they use the same SWR key and the request is deduped, cached and shared automatically.
Also, the application now has the ability to refetch the data on user focus or network reconnect! That means, when the user’s laptop wakes from sleep or they switch between browser tabs, the data will be refreshed automatically.