Skip to content

Commit 51084be

Browse files
daysaiimsobear
authored andcommitted
* fix: rm localUrl api * fix: rm localUrl * chore: migrate testing-library ref testing-library/dom-testing-library#260 * feat: add AppRoute render/component props * chore: rm setupFilesAfterEnv * fix: adjust for cr * fix: adjust JS asset to js asset * fix: rm useless cleanup-after-each * feat: add AppRouteComponentProps ts * chore: update version * fix: interface match to Match
1 parent e1cba6e commit 51084be

File tree

8 files changed

+281
-96
lines changed

8 files changed

+281
-96
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ice/stark",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "Icestark is a JavaScript library for multiple projects, Ice workbench solution.",
55
"scripts": {
66
"build": "rm -rf lib && tsc",
@@ -46,6 +46,8 @@
4646
"@commitlint/cli": "^7.5.2",
4747
"@commitlint/config-conventional": "^7.5.0",
4848
"@ice/spec": "^0.1.4",
49+
"@testing-library/react": "^9.3.2",
50+
"@testing-library/jest-dom": "^4.2.3",
4951
"@types/jest": "^24.0.12",
5052
"@types/node": "^12.0.0",
5153
"@types/path-to-regexp": "^1.7.0",
@@ -54,13 +56,11 @@
5456
"@types/url-parse": "^1.4.3",
5557
"codecov": "^3.4.0",
5658
"eslint": "^5.16.0",
57-
"stylelint": "^10.1.0",
5859
"husky": "^2.2.0",
5960
"jest": "^24.7.1",
60-
"jest-dom": "^3.4.0",
6161
"react": "^16.7.0",
6262
"react-dom": "^16.7.0",
63-
"react-testing-library": "^7.0.0",
63+
"stylelint": "^10.1.0",
6464
"ts-jest": "^24.0.2",
6565
"typescript": "^3.4.4"
6666
},

packages/icestark-app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@
3838
"@commitlint/cli": "^7.5.2",
3939
"@commitlint/config-conventional": "^7.5.0",
4040
"@ice/spec": "^0.1.4",
41+
"@testing-library/jest-dom": "^4.2.3",
4142
"@types/jest": "^24.0.12",
4243
"@types/node": "^12.0.0",
4344
"codecov": "^3.4.0",
4445
"eslint": "^5.16.0",
45-
"stylelint": "^10.1.0",
4646
"husky": "^2.2.0",
4747
"jest": "^24.7.1",
48-
"jest-dom": "^3.4.0",
48+
"stylelint": "^10.1.0",
4949
"ts-jest": "^24.0.2",
5050
"typescript": "^3.4.4"
5151
},

packages/icestark-app/tests/index.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import 'jest-dom/extend-expect';
1+
import '@testing-library/jest-dom/extend-expect';
22

33
import {
44
getBasename,

src/AppRoute.tsx

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import * as ReactDOM from 'react-dom';
3+
import { AppHistory } from './appHistory';
34
import { loadAssets, emptyAssets } from './handleAssets';
4-
import { ICESTSRK_NOT_FOUND } from './constant';
55
import { setCache, getCache } from './cache';
66

77
const statusElementId = 'icestarkStatusContainer';
@@ -23,6 +23,25 @@ interface AppRouteState {
2323
// "hashbang" - “ajax crawlable” (deprecated by Google) hashes like #!/ and #!/sunshine/lollipops
2424
type hashType = 'hashbang' | 'noslash' | 'slash';
2525

26+
interface Match<Params extends { [K in keyof Params]?: string } = {}> {
27+
params: Params;
28+
isExact: boolean;
29+
path: string;
30+
url: string;
31+
}
32+
33+
interface Location<Query extends { [K in keyof Query]?: string } = {}> {
34+
pathname: string;
35+
query: Query;
36+
hash: string;
37+
}
38+
39+
export interface AppRouteComponentProps<Params extends { [K in keyof Params]?: string } = {}> {
40+
match: Match<Params>;
41+
location: Location;
42+
history: AppHistory;
43+
}
44+
2645
export interface AppConfig {
2746
title?: string;
2847
hashType?: boolean | hashType;
@@ -35,11 +54,12 @@ export interface AppConfig {
3554

3655
export interface AppRouteProps extends AppConfig {
3756
path: string | string[];
38-
url: string | string[];
57+
url?: string | string[];
3958
useShadow?: boolean;
4059
ErrorComponent?: any;
4160
LoadingComponent?: any;
42-
NotFoundComponent?: any;
61+
component?: React.ReactElement;
62+
render?: (props?: AppRouteComponentProps) => React.ReactElement;
4363
forceRenderCount?: number;
4464
onAppEnter?: (appConfig: AppConfig) => void;
4565
onAppLeave?: (appConfig: AppConfig) => void;
@@ -60,8 +80,6 @@ function getAppConfig(appRouteProps: AppRouteProps): AppConfig {
6080
'useShadow',
6181
'ErrorComponent',
6282
'LoadingComponent',
63-
'NotFoundComponent',
64-
'useShadow',
6583
'onAppEnter',
6684
'onAppLeave',
6785
];
@@ -84,8 +102,6 @@ export default class AppRoute extends React.Component<AppRouteProps, AppRouteSta
84102

85103
private unmounted: boolean = false;
86104

87-
private triggerNotFound: boolean = false;
88-
89105
static defaultProps = {
90106
useShadow: false,
91107
exact: false,
@@ -129,13 +145,11 @@ export default class AppRoute extends React.Component<AppRouteProps, AppRouteSta
129145
*/
130146
renderChild = (prevAppConfig?: AppConfig): void => {
131147
const {
132-
path,
133148
url,
134149
title,
135150
rootId,
136151
ErrorComponent,
137152
LoadingComponent,
138-
NotFoundComponent,
139153
useShadow,
140154
onAppEnter,
141155
onAppLeave,
@@ -162,7 +176,7 @@ export default class AppRoute extends React.Component<AppRouteProps, AppRouteSta
162176
this.removeElementFromBase(rootId);
163177
let rootElement: any = this.appendElementToBase(rootId);
164178

165-
// Prevent duplicate creation of shadowRoot
179+
// prevent duplicate creation of shadowRoot
166180
if (useShadow && !rootElement.shadowRoot) {
167181
rootElement = rootElement.attachShadow
168182
? rootElement.attachShadow({ mode: 'open', delegatesFocus: false })
@@ -171,25 +185,15 @@ export default class AppRoute extends React.Component<AppRouteProps, AppRouteSta
171185

172186
setCache('root', rootElement);
173187

174-
// Empty useless assets before loading
188+
// empty useless assets before loading
175189
emptyAssets(useShadow);
176190

177-
// Handle NotFound
178-
if (path === ICESTSRK_NOT_FOUND && url === ICESTSRK_NOT_FOUND) {
179-
// loadAssets callback maybe slower than render NotFoundComponent
180-
this.triggerNotFound = true;
181-
this.renderStatusElement(NotFoundComponent);
182-
return;
183-
}
184-
185-
this.triggerNotFound = false;
186-
187191
if (title) document.title = title;
188192

189-
// Generate bundleList
193+
// generate bundleList
190194
const bundleList: string[] = Array.isArray(url) ? url : [url];
191195

192-
// Handle loading
196+
// handle loading
193197
this.setState({ cssLoading: true });
194198
this.renderStatusElement(LoadingComponent);
195199

@@ -202,13 +206,12 @@ export default class AppRoute extends React.Component<AppRouteProps, AppRouteSta
202206
if (err) {
203207
// Handle error
204208
this.renderStatusElement(ErrorComponent, { err });
209+
this.removeElementFromBase(rootId);
210+
this.setState({ cssLoading: false });
205211
return true;
206212
}
207213

208-
if (!this.triggerNotFound) {
209-
// loadAssets callback maybe slower than render NotFoundComponent
210-
this.removeElementFromBase(statusElementId);
211-
}
214+
this.removeElementFromBase(statusElementId);
212215

213216
return this.unmounted;
214217
},

src/AppRouter.tsx

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as React from 'react';
22
import * as urlParse from 'url-parse';
3-
import AppRoute, { AppConfig, AppRouteProps } from './AppRoute';
3+
import { AppConfig, AppRouteProps, AppRouteComponentProps } from './AppRoute';
4+
import appHistory from './appHistory';
45
import matchPath from './matchPath';
56
import { recordAssets } from './handleAssets';
67
import { ICESTSRK_NOT_FOUND } from './constant';
@@ -51,13 +52,25 @@ function getHashPath(hash: string = '/'): string {
5152
return searchIndex === -1 ? hashPath : hashPath.substr(0, searchIndex);
5253
}
5354

55+
/**
56+
* Render Component, compatible with Component and <Component>
57+
*/
58+
function renderComponent(Component: any, props = {}): React.ReactElement {
59+
return React.isValidElement(Component) ? (
60+
React.cloneElement(Component, props)
61+
) : (
62+
<Component {...props} />
63+
);
64+
}
65+
5466
export default class AppRouter extends React.Component<AppRouterProps, AppRouterState> {
5567
private originalPush: OriginalStateFunction = window.history.pushState;
5668

5769
private originalReplace: OriginalStateFunction = window.history.replaceState;
5870

5971
static defaultProps = {
60-
ErrorComponent: <div>js bundle loaded error</div>,
72+
onRouteChange: () => {},
73+
ErrorComponent: ({ err }) => <div>{err}</div>,
6174
NotFoundComponent: <div>NotFound</div>,
6275
useShadow: false,
6376
};
@@ -76,15 +89,21 @@ export default class AppRouter extends React.Component<AppRouterProps, AppRouter
7689
this.handleRouteChange(location.href, 'init');
7790

7891
// render NotFoundComponent eventListener
79-
window.addEventListener('icestark:not-found', () => {
80-
this.setState({ url: ICESTSRK_NOT_FOUND });
81-
});
92+
window.addEventListener('icestark:not-found', this.triggerNotFound);
8293
}
8394

8495
componentWillUnmount() {
8596
this.unHijackHistory();
97+
window.removeEventListener('icestark:not-found', this.triggerNotFound);
8698
}
8799

100+
/**
101+
* Trigger NotFound
102+
*/
103+
triggerNotFound = () => {
104+
this.setState({ url: ICESTSRK_NOT_FOUND });
105+
};
106+
88107
/**
89108
* Hijack window.history
90109
*/
@@ -103,7 +122,7 @@ export default class AppRouter extends React.Component<AppRouterProps, AppRouter
103122
};
104123

105124
/**
106-
* Unhijacking history
125+
* Unhijack window.history
107126
*/
108127
unHijackHistory = (): void => {
109128
window.history.pushState = this.originalPush;
@@ -157,7 +176,6 @@ export default class AppRouter extends React.Component<AppRouterProps, AppRouter
157176
const { url, forceRenderCount } = this.state;
158177

159178
const { pathname, query, hash } = urlParse(url, true);
160-
const { localUrl } = query;
161179

162180
let match: any = null;
163181
let element: any;
@@ -187,25 +205,30 @@ export default class AppRouter extends React.Component<AppRouterProps, AppRouter
187205
onAppEnter,
188206
onAppLeave,
189207
};
190-
if (localUrl) {
191-
extraProps.url = localUrl;
192-
}
193208

194209
if (match) {
195-
const { path, basename } = element.props as AppRouteProps;
210+
const { path, basename, render, component } = element.props as AppRouteProps;
211+
212+
const commonProps: AppRouteComponentProps = {
213+
location: { pathname, query, hash },
214+
match,
215+
history: appHistory,
216+
};
217+
218+
if (component) {
219+
return renderComponent(component, commonProps);
220+
}
221+
222+
if (render && typeof render === 'function') {
223+
return render(commonProps);
224+
}
196225

226+
// render AppRoute
197227
setCache('basename', basename || (Array.isArray(path) ? path[0] : path));
198228

199229
return React.cloneElement(element, extraProps);
200230
}
201231

202-
return (
203-
<AppRoute
204-
path={ICESTSRK_NOT_FOUND}
205-
url={ICESTSRK_NOT_FOUND}
206-
NotFoundComponent={NotFoundComponent}
207-
useShadow={useShadow}
208-
/>
209-
);
232+
return renderComponent(NotFoundComponent, {});
210233
}
211234
}

src/appHistory.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
const appHistory = {
2-
push: (url: string) => {
1+
export interface AppHistory {
2+
push(path: string): void;
3+
replace(path: string): void;
4+
}
5+
6+
const appHistory: AppHistory = {
7+
push: (path: string) => {
38
window.history.pushState(
49
{
510
forceRender: true,
611
},
712
null,
8-
url,
13+
path,
914
);
1015
},
11-
replace: (url: string) => {
16+
replace: (path: string) => {
1217
window.history.replaceState(
1318
{
1419
forceRender: true,
1520
},
1621
null,
17-
url,
22+
path,
1823
);
1924
},
2025
};

src/handleAssets.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function loadAsset(
3939
element.addEventListener(
4040
'error',
4141
() => {
42-
callback(isCss ? undefined : new Error(`JS asset loaded error: ${url}`));
42+
callback(isCss ? undefined : `js asset loaded error: ${url}`);
4343
},
4444
false,
4545
);

0 commit comments

Comments
 (0)