mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 22:36:31 +08:00
perf: better async component (#43982)
* perf: better async component * feat: useFetch * chore: code clean * chore: code clean * chore: fix lint * type: enhance
This commit is contained in:
parent
4da3922a2c
commit
d1f8b500df
@ -1,23 +1,28 @@
|
||||
export default function use(promise: any) {
|
||||
if (promise.status === 'fulfilled') {
|
||||
return promise.value;
|
||||
export default function use<T>(promise: PromiseLike<T>): T {
|
||||
const internal: PromiseLike<T> & {
|
||||
status?: 'pending' | 'fulfilled' | 'rejected';
|
||||
value?: T;
|
||||
reason?: any;
|
||||
} = promise;
|
||||
if (internal.status === 'fulfilled') {
|
||||
return internal.value;
|
||||
}
|
||||
if (promise.status === 'rejected') {
|
||||
throw promise.reason;
|
||||
} else if (promise.status === 'pending') {
|
||||
throw promise;
|
||||
if (internal.status === 'rejected') {
|
||||
throw internal.reason;
|
||||
} else if (internal.status === 'pending') {
|
||||
throw internal;
|
||||
} else {
|
||||
promise.status = 'pending';
|
||||
promise.then(
|
||||
internal.status = 'pending';
|
||||
internal.then(
|
||||
(result) => {
|
||||
promise.status = 'fulfilled';
|
||||
promise.value = result;
|
||||
internal.status = 'fulfilled';
|
||||
internal.value = result;
|
||||
},
|
||||
(reason) => {
|
||||
promise.status = 'rejected';
|
||||
promise.reason = reason;
|
||||
internal.status = 'rejected';
|
||||
internal.reason = reason;
|
||||
},
|
||||
);
|
||||
throw promise;
|
||||
throw internal;
|
||||
}
|
||||
}
|
||||
|
21
.dumi/hooks/useFetch/cache.ts
Normal file
21
.dumi/hooks/useFetch/cache.ts
Normal file
@ -0,0 +1,21 @@
|
||||
export default class FetchCache {
|
||||
private cache: Map<string, PromiseLike<any>> = new Map();
|
||||
|
||||
get(key: string) {
|
||||
return this.cache.get(key);
|
||||
}
|
||||
|
||||
set(key: string, value: PromiseLike<any>) {
|
||||
this.cache.set(key, value);
|
||||
}
|
||||
|
||||
promise<T>(key: string, promiseFn: () => PromiseLike<T>): PromiseLike<T> {
|
||||
const cached = this.get(key);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const promise = promiseFn();
|
||||
this.set(key, promise);
|
||||
return promise;
|
||||
}
|
||||
}
|
20
.dumi/hooks/useFetch/index.ts
Normal file
20
.dumi/hooks/useFetch/index.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import fetch from 'cross-fetch';
|
||||
import use from '../use';
|
||||
import FetchCache from './cache';
|
||||
|
||||
const cache = new FetchCache();
|
||||
|
||||
const useFetch = <T>(options: string | { request: () => PromiseLike<T>; key: string }) => {
|
||||
let request;
|
||||
let key;
|
||||
if (typeof options === 'string') {
|
||||
request = () => fetch(options).then((res) => res.json());
|
||||
key = options;
|
||||
} else {
|
||||
request = options.request;
|
||||
key = options.key;
|
||||
}
|
||||
return use(cache.promise<T>(key, request));
|
||||
};
|
||||
|
||||
export default useFetch;
|
@ -1,6 +1,5 @@
|
||||
import { css } from 'antd-style';
|
||||
import fetch from 'cross-fetch';
|
||||
import use from '../../../hooks/use';
|
||||
import useFetch from '../../../hooks/useFetch';
|
||||
|
||||
export interface Author {
|
||||
avatar: string;
|
||||
@ -81,12 +80,8 @@ export function preLoad(list: string[]) {
|
||||
}
|
||||
}
|
||||
|
||||
const promise = fetch(`https://render.alipay.com/p/h5data/antd4-config_website-h5data.json`).then(
|
||||
(res) => res.json(),
|
||||
);
|
||||
|
||||
export function useSiteData(): [Partial<SiteData>, boolean] {
|
||||
return use(promise);
|
||||
export function useSiteData(): Partial<SiteData> {
|
||||
return useFetch('https://render.alipay.com/p/h5data/antd4-config_website-h5data.json');
|
||||
}
|
||||
|
||||
export const getCarouselStyle = () => ({
|
||||
|
@ -1,9 +1,10 @@
|
||||
/* eslint-disable global-require */
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { createStyles } from 'antd-style';
|
||||
import { HistoryOutlined } from '@ant-design/icons';
|
||||
import { Timeline, Button, Drawer, Typography } from 'antd';
|
||||
import { Button, Drawer, Timeline, Typography } from 'antd';
|
||||
import useLocale from '../../../hooks/useLocale';
|
||||
import useFetch from '../../../hooks/useFetch';
|
||||
|
||||
const useStyle = createStyles(({ token, css }) => ({
|
||||
history: css`
|
||||
@ -85,26 +86,27 @@ function ParseChangelog(props: { changelog: string; refs: string[]; styles: any
|
||||
}
|
||||
|
||||
function useChangelog(componentPath, lang) {
|
||||
const [list, setList] =
|
||||
React.useState<{ version: string; changelog: string; refs: string[] }[]>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
const cnData = require('../../../preset/components-changelog-cn.json');
|
||||
const enData = require('../../../preset/components-changelog-en.json');
|
||||
const data = useFetch(
|
||||
lang === 'cn'
|
||||
? {
|
||||
key: 'component-changelog-cn',
|
||||
request: () => import('../../../preset/components-changelog-cn.json'),
|
||||
}
|
||||
: {
|
||||
key: 'component-changelog-en',
|
||||
request: () => import('../../../preset/components-changelog-en.json'),
|
||||
},
|
||||
);
|
||||
|
||||
return useMemo(() => {
|
||||
const component = componentPath.replace(/-/g, '');
|
||||
|
||||
const mergedData = lang === 'cn' ? cnData : enData;
|
||||
const componentName = Object.keys(mergedData).find(
|
||||
const componentName = Object.keys(data).find(
|
||||
(name) => name.toLowerCase() === component.toLowerCase(),
|
||||
);
|
||||
|
||||
const componentChangelog = mergedData[componentName];
|
||||
|
||||
setList(componentChangelog || []);
|
||||
}, [componentPath]);
|
||||
|
||||
return list || [];
|
||||
return data[componentName];
|
||||
}, [data, componentPath]);
|
||||
}
|
||||
|
||||
export default function ComponentChangelog(props: ComponentChangelogProps) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import type { ComponentChangelogProps } from './ComponentChangelog';
|
||||
|
||||
const ComponentChangelog = React.lazy(() => import('./ComponentChangelog'));
|
||||
import ComponentChangelog from './ComponentChangelog';
|
||||
|
||||
export default (props: ComponentChangelogProps) => (
|
||||
<React.Suspense fallback={null}>
|
||||
|
@ -245,7 +245,6 @@ const Content: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
|
||||
{pathname.startsWith('/components/') && <ComponentChangelog pathname={pathname} />}
|
||||
</Typography.Title>
|
||||
) : null}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* eslint-disable no-loop-func */
|
||||
/* eslint-disable no-loop-func, no-console */
|
||||
// Collect from `changelog.md` to get all components changelog
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
|
Loading…
Reference in New Issue
Block a user