Commit 82138770 by Wee

feat: support async component

parent e562cc16
es es
.build.es5
.build.es6
/dist /dist
/lib
node_modules node_modules
umd umd
!rollup.config.js !rollup.config.js
/coverage /coverage
/npm-debug.log /npm-debug.log
/.rts2_cache*
\ No newline at end of file
...@@ -170,6 +170,24 @@ const LiveRoute = withRouter(NotLiveRoute) ...@@ -170,6 +170,24 @@ const LiveRoute = withRouter(NotLiveRoute)
<LiveRoute path="/list" livePath="/user/:id" component={List} forceUnmount={(location, match)=> match.params.id === 27}/> <LiveRoute path="/list" livePath="/user/:id" component={List} forceUnmount={(location, match)=> match.params.id === 27}/>
``` ```
### ensureDidMount
ensureDidMount is useful when using a route with `react-loadable`. Cause `react-loadable` will load the route component asynchronous. So the route component must give a hint to help react-live-route know when the real component is loaded so the DOM could be got.
```jsx
const LoadableItems = Loadable({
loader: () => import("./list"),
loading: () => () => <p>xxx</p>
})
```
`List` item:
```jsx
componentDidMount() {
this.props.ensureDidMount()
}
```
## Licence ## Licence
MIT MIT
This source diff could not be displayed because it is too large. You can view the blob instead.
{ {
"name": "react-live-route", "name": "react-live-route",
"version": "3.0.7", "version": "3.1.0",
"description": "A living route for react-router v4", "description": "A living route for react-router v4",
"repository": "fi3ework/react-live-route", "repository": "fi3ework/react-live-route",
"license": "MIT", "license": "MIT",
......
...@@ -10,8 +10,10 @@ import warning from 'tiny-warning' ...@@ -10,8 +10,10 @@ import warning from 'tiny-warning'
declare var __DEV__: boolean declare var __DEV__: boolean
function debugLog(message: any) { function debugLog(...message: any) {
console.log(message) // if (__DEV__) {
// console.log(...message)
// }
} }
function isEmptyChildren(children) { function isEmptyChildren(children) {
...@@ -29,19 +31,25 @@ interface IMatchOptions { ...@@ -29,19 +31,25 @@ interface IMatchOptions {
enum SideEffect { enum SideEffect {
SAVE_DOM_SCROLL = 'SAVE_DOM_SCROLL', SAVE_DOM_SCROLL = 'SAVE_DOM_SCROLL',
CLEAR_DOM_DATA = 'CLEAR_DOM_SCROLL', RESTORE_DOM_SCROLL = 'RESTORE_DOM_SCROLL',
CLEAR_DOM_SCROLL = 'CLEAR_DOM_SCROLL',
RESET_SCROLL = 'RESET_SCROLL',
HIDE_DOM = 'HIDE_DOM', HIDE_DOM = 'HIDE_DOM',
SHOW_DOM = 'SHOW_DOM', SHOW_DOM = 'SHOW_DOM',
CLEAR_DOM_DATA = 'CLEAR_DOM_DATA',
ON_REAPPEAR_HOOK = 'ON_REAPPEAR_HOOK', ON_REAPPEAR_HOOK = 'ON_REAPPEAR_HOOK',
ON_HIDE_HOOK = 'ON_HIDE_HOOK', ON_HIDE_HOOK = 'ON_HIDE_HOOK',
NO_SIDE_EFFECT = 'NO_SIDE_EFFECT' NO_SIDE_EFFECT = 'NO_SIDE_EFFECT'
} }
enum LiveState { enum LiveState {
NORMAL_RENDER_MATCHED = 'normal matched render',
NORMAL_RENDER_UNMATCHED = 'normal unmatched render (unmount)',
NORMAL_RENDER_ON_INIT = 'normal render (matched or unmatched)', NORMAL_RENDER_ON_INIT = 'normal render (matched or unmatched)',
HIDE_RENDER = 'hide route when livePath matched' NORMAL_RENDER_MATCHED = 'normal matched render',
HIDE_RENDER = 'hide route when livePath matched',
NORMAL_RENDER_UNMATCHED = 'normal unmatched render (unmount)'
} }
type OnRoutingHook = ( type OnRoutingHook = (
...@@ -82,6 +90,12 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -82,6 +90,12 @@ class LiveRoute extends React.Component<PropsType, any> {
public componentDidUpdate(prevProps, prevState) { public componentDidUpdate(prevProps, prevState) {
this.performSideEffects(this.currentSideEffect, [SideEffect.ON_REAPPEAR_HOOK, SideEffect.CLEAR_DOM_DATA]) this.performSideEffects(this.currentSideEffect, [SideEffect.ON_REAPPEAR_HOOK, SideEffect.CLEAR_DOM_DATA])
this.performSideEffects(this.currentSideEffect, [
SideEffect.SHOW_DOM,
SideEffect.RESTORE_DOM_SCROLL,
SideEffect.CLEAR_DOM_SCROLL
])
this.performSideEffects(this.currentSideEffect, [SideEffect.RESET_SCROLL])
this.getRouteDom() this.getRouteDom()
} }
...@@ -95,7 +109,6 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -95,7 +109,6 @@ class LiveRoute extends React.Component<PropsType, any> {
public getRouteDom = () => { public getRouteDom = () => {
let routeDom = ReactDOM.findDOMNode(this) let routeDom = ReactDOM.findDOMNode(this)
this.routeDom = (routeDom as CacheDom) || this.routeDom this.routeDom = (routeDom as CacheDom) || this.routeDom
console.log(this.routeDom)
} }
public hideRoute() { public hideRoute() {
...@@ -136,6 +149,13 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -136,6 +149,13 @@ class LiveRoute extends React.Component<PropsType, any> {
} }
} }
// reset scroll position
public resetScrollPosition() {
if (scroll && this.routeDom) {
window.scrollTo(0, 0)
}
}
// clear scroll position // clear scroll position
public clearDomData() { public clearDomData() {
if (this.doesRouteEnableLive()) { if (this.doesRouteEnableLive()) {
...@@ -178,6 +198,7 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -178,6 +198,7 @@ class LiveRoute extends React.Component<PropsType, any> {
} }
public performSideEffects = (sideEffects: SideEffect[], range: SideEffect[]) => { public performSideEffects = (sideEffects: SideEffect[], range: SideEffect[]) => {
debugLog(`${this.props.name} perform side effects:`, sideEffects, range)
const sideEffectsToRun = sideEffects.filter(item => range.includes(item)) const sideEffectsToRun = sideEffects.filter(item => range.includes(item))
sideEffectsToRun.forEach((sideEffect, index) => { sideEffectsToRun.forEach((sideEffect, index) => {
switch (sideEffect) { switch (sideEffect) {
...@@ -187,12 +208,24 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -187,12 +208,24 @@ class LiveRoute extends React.Component<PropsType, any> {
case SideEffect.HIDE_DOM: case SideEffect.HIDE_DOM:
this.hideRoute() this.hideRoute()
break break
case SideEffect.SHOW_DOM:
this.showRoute()
break
case SideEffect.RESTORE_DOM_SCROLL:
this.restoreScrollPosition()
break
case SideEffect.ON_REAPPEAR_HOOK: case SideEffect.ON_REAPPEAR_HOOK:
this.onHook('onReappear') this.onHook('onReappear')
break break
case SideEffect.ON_HIDE_HOOK: case SideEffect.ON_HIDE_HOOK:
this.onHook('onHide') this.onHook('onHide')
break break
case SideEffect.CLEAR_DOM_SCROLL:
this.clearScroll()
break
case SideEffect.RESET_SCROLL:
this.resetScrollPosition()
break
case SideEffect.CLEAR_DOM_DATA: case SideEffect.CLEAR_DOM_DATA:
this.clearScroll() this.clearScroll()
this.clearDomData() this.clearDomData()
...@@ -205,6 +238,7 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -205,6 +238,7 @@ class LiveRoute extends React.Component<PropsType, any> {
public getSnapshotBeforeUpdate(prevProps, prevState) { public getSnapshotBeforeUpdate(prevProps, prevState) {
this.performSideEffects(this.currentSideEffect, [SideEffect.SAVE_DOM_SCROLL, SideEffect.HIDE_DOM]) this.performSideEffects(this.currentSideEffect, [SideEffect.SAVE_DOM_SCROLL, SideEffect.HIDE_DOM])
return null
} }
public onHook = (hookName: 'onHide' | 'onReappear') => { public onHook = (hookName: 'onHide' | 'onReappear') => {
...@@ -276,6 +310,7 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -276,6 +310,7 @@ class LiveRoute extends React.Component<PropsType, any> {
(this.liveState === LiveState.NORMAL_RENDER_ON_INIT || this.liveState === LiveState.NORMAL_RENDER_UNMATCHED)) (this.liveState === LiveState.NORMAL_RENDER_ON_INIT || this.liveState === LiveState.NORMAL_RENDER_UNMATCHED))
) { ) {
debugLog('--- not match ---') debugLog('--- not match ---')
this.currentSideEffect = [SideEffect.CLEAR_DOM_SCROLL]
this.liveState = LiveState.NORMAL_RENDER_UNMATCHED this.liveState = LiveState.NORMAL_RENDER_UNMATCHED
return null return null
} }
...@@ -283,13 +318,16 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -283,13 +318,16 @@ class LiveRoute extends React.Component<PropsType, any> {
// normal render || hide render // normal render || hide render
if (matchOfPath) { if (matchOfPath) {
debugLog('--- normal match ---') debugLog('--- normal match ---')
this.showRoute() this.currentSideEffect = [SideEffect.RESET_SCROLL]
this.restoreScrollPosition()
this.clearScroll()
// hide ➡️ show // hide ➡️ show
if (this.liveState === LiveState.HIDE_RENDER) { if (this.liveState === LiveState.HIDE_RENDER) {
this.currentSideEffect = [SideEffect.ON_REAPPEAR_HOOK] this.currentSideEffect = [
SideEffect.SHOW_DOM,
SideEffect.RESTORE_DOM_SCROLL,
SideEffect.CLEAR_DOM_SCROLL,
SideEffect.ON_REAPPEAR_HOOK
]
} }
this.liveState = LiveState.NORMAL_RENDER_MATCHED this.liveState = LiveState.NORMAL_RENDER_MATCHED
} else { } else {
...@@ -336,14 +374,14 @@ class LiveRoute extends React.Component<PropsType, any> { ...@@ -336,14 +374,14 @@ class LiveRoute extends React.Component<PropsType, any> {
} }
} }
// const componentInstance = component && React.createElement(component, props)
// normal render from Route // normal render from Route
return children && !isEmptyChildren(children) return children && !isEmptyChildren(children)
? children ? children
: matchAnyway : matchAnyway
? component ? component
? React.createElement(component, props) ? componentInstance
: render : render
? render(props as any) ? render(props as any)
: null : null
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment