|
1 | 1 | # Mutation |
2 | 2 |
|
| 3 | +SWR provides the `mutate` and `useSWRMutation` APIs for mutating remote data and related cache. |
| 4 | + |
| 5 | +## mutate |
| 6 | + |
3 | 7 | ```js |
4 | 8 | mutate(key, data, options) |
5 | 9 | ``` |
6 | 10 |
|
7 | | -## Options |
| 11 | +### API |
8 | 12 |
|
9 | | -- `optimisticData`: data to immediately update the client cache, or a function that receives current data and returns the new client cache data, usually used in optimistic UI. |
10 | | -- `revalidate`: should the cache revalidate once the asynchronous update resolves. |
11 | | -- `populateCache`: should the result of the remote mutation be written to the cache. |
12 | | -- `populateCache`: should the result of the remote mutation be written to the cache, or a function that receives new result and current result as arguments and returns the mutation result. |
13 | | -- `rollbackOnError`: should the cache rollback if the remote mutation errors. |
| 13 | +#### Parameters |
| 14 | + |
| 15 | +- `key`: same as `useSWR`'s `key` |
| 16 | +- `data`: data to update the client cache, or an async function for the remote mutation |
| 17 | +- `options`: accepts the following options |
| 18 | + - `optimisticData(currentData)`: data to immediately update the client cache, or a function that receives current data and returns the new client cache data, usually used in optimistic UI. |
| 19 | + - `revalidate = true`: should the cache revalidate once the asynchronous update resolves. |
| 20 | + - `populateCache = true`: should the result of the remote mutation be written to the cache, or a function that receives new result and current result as arguments and returns the mutation result. |
| 21 | + - `rollbackOnError = true`: should the cache rollback if the remote mutation errors. |
14 | 22 |
|
15 | 23 | ## Revalidate |
16 | 24 |
|
@@ -239,3 +247,121 @@ function Profile () { |
239 | 247 | ) |
240 | 248 | } |
241 | 249 | ``` |
| 250 | + |
| 251 | +## useSWRMutation |
| 252 | + |
| 253 | +SWR also provides `useSWRMutation` as a hook for remote mutations. The remote mutations are only triggered manually, instead of automatically like `useSWR`. |
| 254 | + |
| 255 | +```jsx |
| 256 | +import useSWRMutation from 'swr/mutation' |
| 257 | + |
| 258 | +async function getData(url, { arg }) { |
| 259 | + // Fetcher implementation. |
| 260 | + // The extra argument will be passed via the `arg` property of the 2nd parameter. |
| 261 | + // For the example below, `arg` will be `'my_token'` |
| 262 | +} |
| 263 | + |
| 264 | +// A useSWR + mutate like API, but it will never start the request. |
| 265 | +const { data, error, trigger, reset, isMutating } = useSWRMutation('/api/user', getData, options?) |
| 266 | +trigger('my_token'); |
| 267 | +``` |
| 268 | +
|
| 269 | +### API |
| 270 | +
|
| 271 | +#### Parameters |
| 272 | +
|
| 273 | +- `key`: same as `useSWR`'s `key` |
| 274 | +- `fetcher(key, { arg })`: an async function for remote mutation |
| 275 | +- `options`: accepts the following options |
| 276 | + - `optimisticData(currentData)`: same as `mutate`'s `optimisticData` |
| 277 | + - `revalidate = true`: same as `mutate`'s `revalidate` |
| 278 | + - `populateCache = false`: same as `mutate`'s `populateCache`, but the default is `false` |
| 279 | + - `rollbackOnError = true`: same as `mutate`'s `rollbackOnError` |
| 280 | + - `onSuccess(data, key, config)`: callback function when a remote mutation has been finished successfully |
| 281 | + - `onError(err, key, config)`: callback function when a remote mutation has returned an error |
| 282 | +
|
| 283 | +#### Return Values |
| 284 | +
|
| 285 | +- `data`: data for the given key returned from `fetcher` |
| 286 | +- `error`: error thrown by `fetcher` (or undefined) |
| 287 | +- `trigger(arg, options)`: a function to trigger a remote mutation |
| 288 | +- `reset`: a function to reset the state (`data`, `error`, `isMutating`) |
| 289 | +- `isMutating`: if there's an ongoing remote mutation |
| 290 | +
|
| 291 | +### Basic Examples |
| 292 | +
|
| 293 | +```jsx |
| 294 | +import useSWRMutation from 'swr/mutation' |
| 295 | + |
| 296 | +async function sendRequest(url, { arg }) { |
| 297 | + return fetch(url, { |
| 298 | + method: 'POST', |
| 299 | + body: JSON.stringify(arg) |
| 300 | + }) |
| 301 | +} |
| 302 | + |
| 303 | +function App() { |
| 304 | + const { trigger } = useSWRMutation('/api/user', sendRequest, /* options */) |
| 305 | + |
| 306 | + return ( |
| 307 | + <button |
| 308 | + onClick={async () => { |
| 309 | + try { |
| 310 | + const result = await trigger({ username: 'johndoe' }, /* options */) |
| 311 | + } catch (e) { |
| 312 | + // error handling |
| 313 | + } |
| 314 | + }} |
| 315 | + > |
| 316 | + Create User |
| 317 | + </button> |
| 318 | + ) |
| 319 | +} |
| 320 | +``` |
| 321 | +
|
| 322 | +If you want to use the mutation results in rendering, you can get them from the return values of `useSWRMutation`. |
| 323 | +
|
| 324 | +```jsx |
| 325 | +const { trigger, data, error } = useSWRMutation('/api/user', sendRequest) |
| 326 | +``` |
| 327 | +
|
| 328 | +`useSWRMutation` shares a cache store with `useSWR`, so it can detect and avoid race conditions between `useSWR`. It also supports `mutate`'s functionalities like optimistic updates and rollback on errors. You can pass these options `useSWRMutation` and its `trigger` function. |
| 329 | +
|
| 330 | +```jsx |
| 331 | +const { trigger } = useSWRMutation('/api/user', updateUser, { |
| 332 | + optimisticData: current => ({ ...current, name: newName }) |
| 333 | +}) |
| 334 | + |
| 335 | +// or |
| 336 | + |
| 337 | +trigger(newName, { |
| 338 | + optimisticData: current => ({ ...current, name: newName }) |
| 339 | +}) |
| 340 | +``` |
| 341 | +
|
| 342 | +### Defer loading data until needed |
| 343 | +
|
| 344 | +You can also use `useSWRMutation` for loading data. `useSWRMutation` never start requesting until `trigger` is called, so you can defer loading data when you actually need it. |
| 345 | +
|
| 346 | +```jsx |
| 347 | +import { useState } from 'react' |
| 348 | +import useSWRMutation from 'swr/mutation' |
| 349 | + |
| 350 | +const fetcher = url => fetch(url).then(res => res.json()) |
| 351 | + |
| 352 | +const Page = () => { |
| 353 | + const [show, setShow] = useState(false) |
| 354 | + // data is undefined until trigger is called |
| 355 | + const { data: user, trigger } = useSWR('/api/user', fetcher); |
| 356 | + |
| 357 | + return ( |
| 358 | + <div> |
| 359 | + <button onClick={() => { |
| 360 | + trigger(); |
| 361 | + setShow(true); |
| 362 | + }}>Show User</button> |
| 363 | + {show && user ? <div>{usre.name}</div> : null} |
| 364 | + </div> |
| 365 | + ); |
| 366 | +} |
| 367 | +``` |
0 commit comments