-
Notifications
You must be signed in to change notification settings - Fork 287
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: [LazyComponent] add
onLoad
event to decorator, and resolve cir…
…cular dependencies
- Loading branch information
Showing
8 changed files
with
192 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import React from 'react'; | ||
import { ComponentsContextInterface } from './interface'; | ||
|
||
export const ComponentsContext = React.createContext<ComponentsContextInterface>({ | ||
addComponent: () => {}, | ||
getComponent: () => null, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import React from 'react'; | ||
import { LazyComponentResult } from '../../utils/lazyComponent'; | ||
|
||
interface ComponentInterfaceWithComponent { | ||
component: React.ComponentType<any>; | ||
type?: 'decorator'; | ||
} | ||
|
||
interface ComponentInterfaceWithUrl { | ||
url: string; | ||
name: string; | ||
} | ||
|
||
interface ComponentInterfaceWithDecorator { | ||
decorator: string; | ||
data: any; | ||
} | ||
|
||
export type ComponentInterface = | ||
| ComponentInterfaceWithComponent | ||
| ComponentInterfaceWithUrl | ||
| ComponentInterfaceWithDecorator; | ||
|
||
interface CallbackParamsWithAsync { | ||
code: string; | ||
async: boolean; | ||
component: React.ComponentType; | ||
} | ||
|
||
interface CallbackParamsWithError { | ||
code: string; | ||
errCode: string; | ||
} | ||
|
||
export interface GetComponentCallback { | ||
(e: CallbackParamsWithAsync | CallbackParamsWithError): void; | ||
} | ||
|
||
export interface ComponentsContextInterface { | ||
addComponent: (code: string, value: ComponentInterface) => void; | ||
getComponent: ( | ||
code: string, | ||
callback?: GetComponentCallback, | ||
) => React.ComponentType<any> | LazyComponentResult | null; | ||
} | ||
|
||
export interface ComponentsMap { | ||
[k: string]: ComponentInterface; | ||
} | ||
|
||
export interface ComponentsProviderProps { | ||
components: ComponentsMap; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import React from 'react'; | ||
import { ComponentsContext } from './ComponentsContext'; | ||
|
||
export function useComponents() { | ||
return React.useContext(ComponentsContext); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React, { Suspense } from 'react'; | ||
import { ErrorBoundary } from '../ErrorBoundary'; | ||
import { LazyComponentPropsWithComponent } from './interface'; | ||
|
||
export const SuspenseWrap: React.FC<LazyComponentPropsWithComponent> = (props) => { | ||
const { component: Comp, onError, fallback, ...rest } = props; | ||
|
||
return Comp ? ( | ||
<ErrorBoundary onError={onError}> | ||
<Suspense fallback={fallback || null}> | ||
<Comp {...rest} /> | ||
</Suspense> | ||
</ErrorBoundary> | ||
) : null; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,36 @@ | ||
import React, { Suspense } from 'react'; | ||
import { ErrorBoundary } from '../..'; | ||
// eslint-disable-next-line import/no-cycle | ||
import { useComponents } from '../ComponentsProvider'; | ||
import React from 'react'; | ||
import { SuspenseWrap } from './SuspenseWrap'; | ||
import { LazyComponentProps, LazyComponentPropsWithCode } from './interface'; | ||
import { useComponents } from '../ComponentsProvider/useComponents'; | ||
|
||
interface LazyComponentBaseProps { | ||
fallback?: NonNullable<React.ReactNode> | null; | ||
onError?: (error: Error, info?: React.ErrorInfo) => void; | ||
[k: string]: any; | ||
} | ||
export type { LazyComponentProps }; | ||
|
||
interface LazyComponentPropsWithComponent extends LazyComponentBaseProps { | ||
component: React.ComponentType; | ||
} | ||
export const LazyComponentWithCode: React.FC<LazyComponentPropsWithCode> = (props) => { | ||
const { code, fallback, onLoad, onError, ...rest } = props; | ||
const { getComponent } = useComponents(); | ||
|
||
interface LazyComponentPropsWithCode extends LazyComponentBaseProps { | ||
code: string; | ||
onLoad?: (e: { async: boolean }) => void; | ||
} | ||
const Comp = getComponent(code, (res) => { | ||
if ('async' in res && onLoad) { | ||
onLoad(res); | ||
} else if ('errCode' in res && onError) { | ||
onError(new Error(res.errCode)); | ||
} | ||
}); | ||
|
||
export type LazyComponentProps = LazyComponentPropsWithComponent | LazyComponentPropsWithCode; | ||
return <SuspenseWrap component={Comp} onError={onError} fallback={fallback} {...rest} />; | ||
}; | ||
|
||
export const LazyComponent: React.FC<LazyComponentProps> = (props) => { | ||
const { getComponent } = useComponents(); | ||
const { component, code, fallback, onLoad, onError, ...rest } = props; | ||
|
||
const Comp = | ||
component || | ||
getComponent(code, (res) => { | ||
if ('async' in res && onLoad) { | ||
onLoad(res); | ||
} else if ('errCode' in res && onError) { | ||
onError(new Error(res.errCode)); | ||
} | ||
}); | ||
|
||
if (component && onLoad) { | ||
onLoad({ async: false, component }); | ||
const { component, code, onLoad, ...rest } = props; | ||
|
||
if (component) { | ||
if (onLoad) { | ||
onLoad({ async: false, component }); | ||
} | ||
return <SuspenseWrap component={component} {...rest} />; | ||
} | ||
|
||
return Comp ? ( | ||
<ErrorBoundary onError={onError}> | ||
<Suspense fallback={fallback || null}> | ||
<Comp {...rest} /> | ||
</Suspense> | ||
</ErrorBoundary> | ||
) : null; | ||
return <LazyComponentWithCode code={code} onLoad={onLoad} {...rest} />; | ||
}; | ||
|
||
export default LazyComponent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
interface LazyComponentBaseProps { | ||
fallback?: NonNullable<React.ReactNode> | null; | ||
onError?: (error: Error, info?: React.ErrorInfo) => void; | ||
[k: string]: any; | ||
} | ||
|
||
export interface LazyComponentPropsWithComponent extends LazyComponentBaseProps { | ||
component: React.ComponentType | null; | ||
} | ||
|
||
export interface LazyComponentPropsWithCode extends LazyComponentBaseProps { | ||
code: string; | ||
onLoad?: (e: { async: boolean; component: React.ComponentType<any> }) => void; | ||
} | ||
|
||
export type LazyComponentProps = LazyComponentPropsWithComponent | LazyComponentPropsWithCode; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters