diff --git a/docs/docs/docs/max/react-query.md b/docs/docs/docs/max/react-query.md
index 180ec5932bd1..f9446e00ae40 100644
--- a/docs/docs/docs/max/react-query.md
+++ b/docs/docs/docs/max/react-query.md
@@ -29,6 +29,14 @@ export default {
}
```
+:::info
+注:在使用时,请务必检查关于 `refetchOnWindowFocus` 的配置项,详见 [运行时配置项](#运行时配置项) 。
+:::
+
+## 版本
+
+默认使用的是 [TanStack Query](https://tanstack.com/query/latest) v4 版本,若需使用最新 v5 版本,手动安装 v5 版本的 `@tanstack/react-query` 与 `@tanstack/react-query-devtools` 依赖即可。
+
## 特性
插件帮你做了几件事,
@@ -66,27 +74,26 @@ export default {
- `devtool`:object
- `queryClient`: object
-比如:
+例子:
```ts
-const API_SERVER = '/path/to/api/server';
-export const reactQuery = {
+// src/app.ts
+
+import { RuntimeReactQueryType } from 'umi';
+
+export const reactQuery: RuntimeReactQueryType = {
devtool: {
initialIsOpen: true,
},
queryClient: {
- defaultOptions: {
- queries: {
- queryFn: async ({ queryKey }) => {
- const res = await fetch(`${API_SERVER}/${queryKey.join('/')}`);
- if (res.status !== 200) {
- throw new Error(res.statusText);
- }
- return res.json();
- }
- }
- }
+ defaultOptions: {
+ queries: {
+ // 🟡 此配置具有的表现往往令人出乎意料,若无特殊需求,请默认关闭
+ refetchOnWindowFocus: false,
+ },
+ },
},
};
```
+注:绝大多数项目中,**你都应该默认设定 `refetchOnWindowFocus: false`** ,否则将引发出人意料的反复获取数据效果(这在 SWR 中被称为 [`revalidateOnFocus`](https://swr.vercel.app/zh-CN/docs/api#options) )。
diff --git a/examples/with-react-query-v5/.umirc.ts b/examples/with-react-query-v5/.umirc.ts
new file mode 100644
index 000000000000..38a5d9a5a541
--- /dev/null
+++ b/examples/with-react-query-v5/.umirc.ts
@@ -0,0 +1,4 @@
+export default {
+ plugins: ['@umijs/plugins/dist/react-query'],
+ reactQuery: {},
+};
diff --git a/examples/with-react-query-v5/app.ts b/examples/with-react-query-v5/app.ts
new file mode 100644
index 000000000000..3dd82a872e80
--- /dev/null
+++ b/examples/with-react-query-v5/app.ts
@@ -0,0 +1,14 @@
+import { RuntimeReactQueryType } from 'umi';
+
+export const reactQuery: RuntimeReactQueryType = {
+ queryClient: {
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ },
+ },
+ },
+ devtool: {
+ buttonPosition: 'bottom-left',
+ },
+};
diff --git a/examples/with-react-query-v5/package.json b/examples/with-react-query-v5/package.json
new file mode 100644
index 000000000000..7dd6b67be53e
--- /dev/null
+++ b/examples/with-react-query-v5/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "@example/with-react-query-v5",
+ "private": true,
+ "scripts": {
+ "build": "umi build",
+ "dev": "umi dev",
+ "start": "npm run dev"
+ },
+ "dependencies": {
+ "@tanstack/react-query": "^5.28.6",
+ "@tanstack/react-query-devtools": "^5.28.6",
+ "umi": "workspace:*"
+ }
+}
diff --git a/examples/with-react-query-v5/pages/index.tsx b/examples/with-react-query-v5/pages/index.tsx
new file mode 100644
index 000000000000..df573f5ae6cf
--- /dev/null
+++ b/examples/with-react-query-v5/pages/index.tsx
@@ -0,0 +1,30 @@
+import { useQuery } from 'umi';
+import '../style.less';
+
+export default function HomePage() {
+ const { isFetching, data } = useQuery({
+ queryKey: ['repoData'],
+ queryFn: () => {
+ return new Promise<{ stargazers_count: number }>((resolve, _) => {
+ setTimeout(async () => {
+ const res = await fetch('https://api.github.com/repos/umijs/umi');
+ const json = await res.json();
+ resolve(json);
+ }, 500);
+ });
+ },
+ });
+
+ return (
+
+
+
UmiJS x react-query v5
+ {isFetching ? (
+
Loading ...
+ ) : (
+
UmiJS has {data?.stargazers_count} stars now!
+ )}
+
+
+ );
+}
diff --git a/examples/with-react-query-v5/readme.md b/examples/with-react-query-v5/readme.md
new file mode 100644
index 000000000000..cfb2bd497bb8
--- /dev/null
+++ b/examples/with-react-query-v5/readme.md
@@ -0,0 +1,3 @@
+# react-query-v5
+
+An example of using [UmiJS](https://umijs.org/zh-CN) with [react-query](https://github.com/TanStack/query) v5.
diff --git a/examples/with-react-query-v5/style.less b/examples/with-react-query-v5/style.less
new file mode 100644
index 000000000000..6f08a19486e5
--- /dev/null
+++ b/examples/with-react-query-v5/style.less
@@ -0,0 +1,22 @@
+body {
+ font-family: 'Lucida Sans', sans-serif;
+}
+
+.container {
+ width: 100%;
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ div {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .title {
+ font-size: 64px;
+ }
+
+}
diff --git a/examples/with-react-query-v5/tsconfig.json b/examples/with-react-query-v5/tsconfig.json
new file mode 100644
index 000000000000..7fa7937c8056
--- /dev/null
+++ b/examples/with-react-query-v5/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "./.umi/tsconfig.json"
+}
diff --git a/examples/with-react-query/app.ts b/examples/with-react-query/app.ts
new file mode 100644
index 000000000000..7433df6cf8a8
--- /dev/null
+++ b/examples/with-react-query/app.ts
@@ -0,0 +1,14 @@
+import { RuntimeReactQueryType } from 'umi';
+
+export const reactQuery: RuntimeReactQueryType = {
+ queryClient: {
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ },
+ },
+ },
+ devtool: {
+ position: 'bottom-left',
+ },
+};
diff --git a/examples/with-react-query/pages/index.tsx b/examples/with-react-query/pages/index.tsx
index d26d1dc11457..eccf592e95b8 100644
--- a/examples/with-react-query/pages/index.tsx
+++ b/examples/with-react-query/pages/index.tsx
@@ -2,7 +2,7 @@ import { useQuery } from 'umi';
import '../style.less';
export default function HomePage() {
- const { isLoading, data } = useQuery(['repoData'], () =>
+ const { isFetching, data } = useQuery(['repoData'], () =>
fetch('https://api.github.com/repos/umijs/umi').then((res) => res.json()),
);
@@ -10,7 +10,7 @@ export default function HomePage() {
UmiJS x react-query
- {isLoading &&
Loading ...
}
+ {isFetching &&
Loading ...
}
{data &&
UmiJS has {data.stargazers_count} stars now!
}
diff --git a/examples/with-react-query/tsconfig.json b/examples/with-react-query/tsconfig.json
new file mode 100644
index 000000000000..7fa7937c8056
--- /dev/null
+++ b/examples/with-react-query/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "./.umi/tsconfig.json"
+}
diff --git a/packages/plugins/src/layout.ts b/packages/plugins/src/layout.ts
index 7fbd6d2c1479..0a711ac4fdfa 100644
--- a/packages/plugins/src/layout.ts
+++ b/packages/plugins/src/layout.ts
@@ -1,7 +1,8 @@
import { existsSync, readFileSync } from 'fs';
import { dirname, join } from 'path';
import { IApi, RUNTIME_TYPE_FILE_NAME } from 'umi';
-import { lodash, Mustache, NpmClientEnum, winPath } from 'umi/plugin-utils';
+import { lodash, Mustache, winPath } from 'umi/plugin-utils';
+import { isFlattedNodeModulesDir } from './utils/npmClient';
import { resolveProjectDep } from './utils/resolveProjectDep';
import { withTmpPath } from './utils/withTmpPath';
@@ -117,21 +118,10 @@ export default (api: IApi) => {
});
api.onGenerateFiles(() => {
- let realNpmClient = api.appData.npmClient;
- // tnpm 作为 npmClient 时,可能使用不同的安装模式
- if (
- api.appData.npmClient === NpmClientEnum.tnpm &&
- api.pkg.tnpm?.mode &&
- [NpmClientEnum.npm, NpmClientEnum.yarn].includes(api.pkg.tnpm.mode)
- ) {
- realNpmClient = api.pkg.tnpm.mode;
- }
// use absolute path to types references in `npm/yarn` will cause case problems.
// https://github.com/umijs/umi/discussions/10947
// https://github.com/umijs/umi/discussions/11570
- const isFlattedDepsDir = [NpmClientEnum.npm, NpmClientEnum.yarn].includes(
- realNpmClient,
- );
+ const isFlattedDepsDir = isFlattedNodeModulesDir(api);
const PKG_TYPE_REFERENCE = `
/// {
+ let currentNpmClient = api.appData.npmClient;
+ // tnpm 作为 npmClient 时,可能使用不同的安装模式
+ const tnpmCompatMode: string | undefined =
+ api.appData.npmClient === NpmClientEnum.tnpm && api.pkg.tnpm?.mode;
+ if (tnpmCompatMode) {
+ if (FLATTED_NPM_CLIENT.includes(api.pkg.tnpm.mode)) {
+ return true;
+ }
+ }
+ const isFlattedDir = FLATTED_NPM_CLIENT.includes(currentNpmClient);
+ return isFlattedDir;
+};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1b0fde386c80..a3e6becd4fae 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1423,6 +1423,18 @@ importers:
specifier: workspace:*
version: link:../../packages/umi
+ examples/with-react-query-v5:
+ dependencies:
+ '@tanstack/react-query':
+ specifier: ^5.28.6
+ version: 5.28.6(react@18.1.0)
+ '@tanstack/react-query-devtools':
+ specifier: ^5.28.6
+ version: 5.28.6(@tanstack/react-query@5.28.6)(react@18.1.0)
+ umi:
+ specifier: workspace:*
+ version: link:../../packages/umi
+
examples/with-react-three-fiber:
dependencies:
'@react-three/drei':
@@ -15868,6 +15880,14 @@ packages:
/@tanstack/query-core@4.24.10:
resolution: {integrity: sha512-2QywqXEAGBIUoTdgn1lAB4/C8QEqwXHj2jrCLeYTk2xVGtLiPEUD8jcMoeB2noclbiW2mMt4+Fq7fZStuz3wAQ==}
+ /@tanstack/query-core@5.28.6:
+ resolution: {integrity: sha512-hnhotV+DnQtvtR3jPvbQMPNMW4KEK0J4k7c609zJ8muiNknm+yoDyMHmxTWM5ZnlZpsz0zOxYFr+mzRJNHWJsA==}
+ dev: false
+
+ /@tanstack/query-devtools@5.28.6:
+ resolution: {integrity: sha512-DXJGqbrsteWU9XehDf6s3k3QxwQqGUlNXpitsF1xbwkYBcDaAakiC6hjJSMfPBHOrbZCnWfAGCVf4vh2D75/xw==}
+ dev: false
+
/@tanstack/react-query-devtools@4.24.10(@tanstack/react-query@4.24.10)(react-dom@17.0.2)(react@17.0.2):
resolution: {integrity: sha512-1uzJNLdLjRsNt4O5ldv1SYPevWvSdHtKIyVJeUv4hSERPEhrKKfa8WC3dBOX24CdLEYH2ndLZW4ZiC9nzSKCtg==}
peerDependencies:
@@ -15908,6 +15928,20 @@ packages:
use-sync-external-store: 1.2.0(react@18.1.0)
dev: false
+ /@tanstack/react-query-devtools@5.28.6(@tanstack/react-query@5.28.6)(react@18.1.0):
+ resolution: {integrity: sha512-xSfskHlM2JkP7WpN89UqhJV2RbFxg8YnOMzQz+EEzWSsgxMI5Crce8HO9pcUAcJce8gSmw93RQwuKNdG3FbT6w==}
+ peerDependencies:
+ '@tanstack/react-query': ^5.28.6
+ react: ^18.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ dependencies:
+ '@tanstack/query-devtools': 5.28.6
+ '@tanstack/react-query': 5.28.6(react@18.1.0)
+ react: 18.1.0
+ dev: false
+
/@tanstack/react-query@4.24.10(react-dom@17.0.2)(react@17.0.2):
resolution: {integrity: sha512-FY1DixytOcNNCydPQXLxuKEV7VSST32CAuJ55BjhDNqASnMLZn+6c30yQBMrODjmWMNwzfjMZnq0Vw7C62Fwow==}
peerDependencies:
@@ -15948,6 +15982,18 @@ packages:
use-sync-external-store: 1.2.0(react@18.1.0)
dev: false
+ /@tanstack/react-query@5.28.6(react@18.1.0):
+ resolution: {integrity: sha512-/DdYuDBSsA21Qbcder1R8Cr/3Nx0ZnA2lgtqKsLMvov8wL4+g0HBz/gWYZPlIsof7iyfQafyhg4wUVUsS3vWZw==}
+ peerDependencies:
+ react: ^18.0.0
+ peerDependenciesMeta:
+ react:
+ optional: true
+ dependencies:
+ '@tanstack/query-core': 5.28.6
+ react: 18.1.0
+ dev: false
+
/@testing-library/dom@9.0.0:
resolution: {integrity: sha512-+/TLgKNFsYUshOY/zXsQOk+PlFQK+eyJ9T13IDVNJEi+M+Un7xlJK+FZKkbGSnf0+7E1G6PlDhkSYQ/GFiruBQ==}
engines: {node: '>=14'}