Skip to content

Commit

Permalink
Merge branch 'master' into benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
shuding committed Aug 18, 2021
2 parents 2f1f502 + 21de0ad commit 0450650
Show file tree
Hide file tree
Showing 78 changed files with 3,995 additions and 2,889 deletions.
3 changes: 2 additions & 1 deletion .codesandbox/ci.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"buildCommand": "build",
"sandboxes": ["swr-basic-p7dg6", "swr-states-4une7", "swr-infinite-jb5bm", "swr-ssr-j9b2y"]
"sandboxes": ["swr-basic-p7dg6", "swr-states-4une7", "swr-infinite-jb5bm", "swr-ssr-j9b2y"],
"node": "14"
}
6 changes: 2 additions & 4 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
dist/**/*
esm/**/*
node_modules
playground
dist/
node_modules
20 changes: 11 additions & 9 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
"impliedStrict": true,
"experimentalObjectRestSpread": true
},
"allowImportExportEverywhere": true
"allowImportExportEverywhere": true,
"project": ["**/tsconfig.json"]
},
"plugins": ["@typescript-eslint", "react-hooks"],
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"prettier/@typescript-eslint",
Expand All @@ -32,16 +32,18 @@
"jest": true
},
"rules": {
"func-names": ["error", "as-needed"],
"no-shadow": "error",
"prefer-const": 0,
"func-names": [2, "as-needed"],
"no-shadow": 2,
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-explicit-any": 0,
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
"@typescript-eslint/explicit-module-boundary-types": 0,
"react-hooks/rules-of-hooks": 2,
"react-hooks/exhaustive-deps": 1,
"react/prop-types": 0
}
}
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @shuding @pacocoursey
* @shuding @huozhi
24 changes: 12 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ on:

jobs:
test:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '14.x'
- run: yarn install
- run: yarn types:check
- run: yarn lint
- run: yarn test
env:
CI: true
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '14.x'
- run: yarn install
- run: yarn types:check
- run: yarn lint
- run: yarn build
- run: yarn test
env:
CI: true
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ esm
.vscode
examples/**/yarn.lock
package-lock.json
playground/**
37 changes: 23 additions & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,37 @@ If possible, you can add other additional context like how this feature can be i

## Open a PR for Bugfix or Feature

### Local Development
### Local Development with Examples

To develop SWR locally, you can use the Vite SWR playground to play with the source code inside the browser. You can follow these steps:
To run SWR locally, you can start it with any example in `examples` folder. You need to setup the example and run command in the root directory for overriding SWR and its dependencies to local assets.

```bash
yarn install
yarn register
First of all, build SWR assets

```sh
# or `yarn watch`
yarn build
yarn prepare:vite
yarn dev:vite
```

To test SSR related features, you need to use the Next.js SWR playground instead:
Install dependency of the target example, for instance `examples/basic`:

```bash
yarn install
yarn register
yarn build
yarn prepare:next
yarn dev:next
```sh
cd examples/basic && yarn
```

After setup, back to the root directory and run:

```sh
# by default it will run next dev for the example
yarn dev-next basic
```

All examples are built with Next.js, so Next.js commands are all supported:

```sh
# if you want to build and start
yarn dev-next basic build
yarn dev-next basic start
```
## Update Documentation

To update the [SWR Documentation](https://swr.vercel.app), you can contribute to the [website repository](https://github.com/vercel/swr-site).
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const { data, error, isValidating, mutate } = useSWR(key, fetcher, options)
#### Options

- `suspense = false`: enable React Suspense mode [(details)](#suspense-mode)
- `fetcher = window.fetch`: the default fetcher function
- `fetcher`: the function to retrieve the remote data source
- `initialData`: initial data to be returned (note: This is per-hook)
- `revalidateOnMount`: enable or disable automatic revalidation when component is mounted (by default revalidation occurs on mount when initialData is not set, use this flag to force behavior)
- `revalidateOnFocus = true`: auto revalidate when window gets focused
Expand Down Expand Up @@ -418,11 +418,13 @@ function Profile() {
<h1>My name is {data.name}.</h1>
<button onClick={async () => {
const newName = data.name.toUpperCase()
// update the local data immediately
mutate({ ...data, name: newName }, false)
// send a request to the API to update the data
await requestUpdateUsername(newName)
// update the local data immediately and revalidate (refetch)
// revalidate (refetch)
// NOTE: key is not required when using useSWR's mutate as it's pre-bound
mutate({ ...data, name: newName })
mutate()
}}>Uppercase my name!</button>
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion examples/autocomplete-suggestions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
"@reach/combobox": "0.5.3",
"@reach/combobox": "0.15.1",
"isomorphic-unfetch": "3.0.0",
"next": "9.3.3",
"react": "16.11.0",
Expand Down
11 changes: 5 additions & 6 deletions examples/axios-typescript/libs/useRequest.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import useSWR, { ConfigInterface, responseInterface } from 'swr'
import useSWR, { SWRConfiguration, SWRResponse } from 'swr'
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'

export type GetRequest = AxiosRequestConfig | null

interface Return<Data, Error>
extends Pick<
responseInterface<AxiosResponse<Data>, AxiosError<Error>>,
'isValidating' | 'revalidate' | 'error' | 'mutate'
SWRResponse<AxiosResponse<Data>, AxiosError<Error>>,
'isValidating' | 'error' | 'mutate'
> {
data: Data | undefined
response: AxiosResponse<Data> | undefined
}

export interface Config<Data = unknown, Error = unknown>
extends Omit<
ConfigInterface<AxiosResponse<Data>, AxiosError<Error>>,
SWRConfiguration<AxiosResponse<Data>, AxiosError<Error>>,
'initialData'
> {
initialData?: Data
Expand All @@ -24,7 +24,7 @@ export default function useRequest<Data = unknown, Error = unknown>(
request: GetRequest,
{ initialData, ...config }: Config<Data, Error> = {}
): Return<Data, Error> {
const { data: response, error, isValidating, revalidate, mutate } = useSWR<
const { data: response, error, isValidating, mutate } = useSWR<
AxiosResponse<Data>,
AxiosError<Error>
>(
Expand Down Expand Up @@ -53,7 +53,6 @@ export default function useRequest<Data = unknown, Error = unknown>(
response,
error,
isValidating,
revalidate,
mutate
}
}
6 changes: 3 additions & 3 deletions examples/focus-revalidate/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { login, logout } from '../libs/auth'
import useSWR from 'swr'

export default () => {
const { data, revalidate } = useSWR('/api/user', fetch)
const { data, mutate } = useSWR('/api/user', fetch)

if (!data) return <h1>loading...</h1>
if (data.loggedIn) {
Expand All @@ -14,15 +14,15 @@ export default () => {
<img src={data.avatar} width={80} />
<Button onClick={() => {
logout()
revalidate() // after logging in/out, we revalidate the SWR
mutate() // after logging in/out, we mutate the SWR
}}>Logout</Button>
</div>
} else {
return <div>
<h1>Please login</h1>
<Button onClick={() => {
login()
revalidate()
mutate()
}}>Login</Button>
</div>
}
Expand Down
2 changes: 1 addition & 1 deletion examples/infinite-scroll/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Download the example:

```bash
curl https://codeload.github.com/vercel/swr/tar.gz/master | tar -xz --strip=2 swr-master/examples/infinite-scroll
cd basic
cd infinite-scroll
```

Install it and run:
Expand Down
8 changes: 4 additions & 4 deletions examples/infinite-scroll/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
"isomorphic-unfetch": "3.0.0",
"next": "10.0.6",
"react": "17.0.1",
"react-dom": "17.0.1",
"isomorphic-unfetch": "3.1.0",
"next": "^10.2.3",
"react": "17.0.2",
"react-dom": "17.0.2",
"swr": "latest"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion examples/infinite-scroll/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default function App() {
<input
value={val}
onChange={(e) => setVal(e.target.value)}
placeholder="facebook/reect"
placeholder="facebook/react"
/>
<button
onClick={() => {
Expand Down
4 changes: 2 additions & 2 deletions examples/infinite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
"license": "MIT",
"dependencies": {
"isomorphic-unfetch": "3.0.0",
"next": "10.0.6",
"next": "latest",
"react": "17.0.1",
"react-dom": "17.0.1",
"swr": "latest"
"swr": "beta"
},
"scripts": {
"dev": "next",
Expand Down
2 changes: 1 addition & 1 deletion examples/infinite/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { useSWRInfinite } from 'swr'
import useSWRInfinite from 'swr/infinite'

import fetch from '../libs/fetch'

Expand Down
16 changes: 10 additions & 6 deletions examples/optimistic-ui-immer/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ export default () => {

async function handleSubmit(event) {
event.preventDefault()
// call mutate to optimistically update the UI
// we use Immer produce to allow us to perform and immutable change
// while coding it as a normal mutation of the same object
// Call mutate to optimistically update the UI.
// We use Immer produce to allow us to perform an immutable change
// while coding it as a normal mutation of the same object.
mutate("/api/data", produce(draftData => {
draftData.push(text)
}), false)
// then we send the request to the API and let mutate
// update the data with the API response
// if this fail it will rollback the optimistic update
// Then we send the request to the API and let mutate
// update the data with the API response.
// Our action may fail in the API function, and the response differ
// from what was optimistically updated, in that case the UI will be
// changed to match the API response.
// The fetch could also fail, in that case the UI will
// be in an incorrect state until the next successful fetch.
mutate('/api/data', await fetch('/api/data', {
method: 'POST',
body: JSON.stringify({ text })
Expand Down
13 changes: 8 additions & 5 deletions examples/optimistic-ui/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ export default () => {

async function handleSubmit(event) {
event.preventDefault()
// mutate current data to optimistically update the UI
// the fetch below could fail, in that case the UI will
// be in an incorrect state
// Call mutate to optimistically update the UI.
mutate('/api/data', [...data, text], false)
// then we send the request to the API and let mutate
// update the data with the API response
// Then we send the request to the API and let mutate
// update the data with the API response.
// Our action may fail in the API function, and the response differ
// from what was optimistically updated, in that case the UI will be
// changed to match the API response.
// The fetch could also fail, in that case the UI will
// be in an incorrect state until the next successful fetch.
mutate('/api/data', await fetch('/api/data', {
method: 'POST',
body: JSON.stringify({ text })
Expand Down
6 changes: 3 additions & 3 deletions examples/refetch-interval/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import fetch from '../libs/fetch'
import useSWR from 'swr'

export default () => {
const { data, revalidate } = useSWR('/api/data', fetch, {
const { data, mutate } = useSWR('/api/data', fetch, {
// revalidate the data per second
refreshInterval: 1000
})
Expand All @@ -21,7 +21,7 @@ export default () => {
ev.preventDefault()
setValue('')
await fetch(`/api/data?add=${value}`)
revalidate()
mutate()
}}>
<input placeholder='enter something' value={value} onChange={ev => setValue(ev.target.value)} />
</form>
Expand All @@ -30,7 +30,7 @@ export default () => {
</ul>
<Button onClick={async () => {
await fetch(`/api/data?clear=1`)
revalidate()
mutate()
}}>Clear All</Button>
</div>
)
Expand Down
12 changes: 12 additions & 0 deletions immutable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import useSWR, { Middleware, SWRHook } from 'swr'
import { withMiddleware } from '../src/utils/with-middleware'

export const immutable: Middleware = useSWRNext => (key, fetcher, config) => {
// Always override all revalidate options.
config.revalidateOnFocus = false
config.revalidateWhenStale = false
config.revalidateOnReconnect = false
return useSWRNext(key, fetcher, config)
}

export default withMiddleware(useSWR as SWRHook, immutable)
Loading

0 comments on commit 0450650

Please sign in to comment.