目前next/router
公开了一个单例API,可以通过以下方式监听其更改:
Router.onRouteChangeStart = myHandler // subscribe
Router.onRouteChangeStart = null // unsubscribe
这带来了一些与架构相关的挑战,因为两个不相关的组件无法同时监听路由状态的变化。
根据对https://github.com/zeit/next.js/issues/2033的讨论,没有计划将next/router
转换为事件发射器/可观察者。
鉴于此,我们如何在Next.js中实现具有共享订阅的路由器?
答案 0 :(得分:1)
到目前为止,我一直很满意的解决方案是在Observables中包含next/router
侦听器方法,并在componentDidMount上为组件创建HLA附加路由器事件。
使用RxJS的示例实现:
// I'm using recompose for and rxjs, but you should be able to modify this code easily
// 1. sharedRouter.js
import Router from 'next/router'
import { Observable } from 'rxjs'
export const routeChangeStart$ = Observable.create(
obs => {
console.log('route: start')
Router.onRouteChangeStart = url => {
obs.next(url)
}
}
).share() // note the .share() operator,
// it ensures that we don't reassign Router.onRouteChangeStart
// every time a new component subscribes to this observable
export const routeChangeComplete$ = Observable.create(
obs => {
Router.onRouteChangeComplete = () => {
console.log('route: complete')
obs.next()
}
}
).share()
export const routeChangeError$ = Observable.create(
obs => {
Router.onRouteChangeError = () => {
console.log('route: error')
obs.next()
}
}
).share()
// 2. appBar/withRouterEvents.js
// This one is attached to our AppNav component
import { lifecycle } from 'recompose'
import * as SharedRouter from './sharedRouter'
const withRouterEvents = lifecycle({
componentDidMount(){
const onStartLoadingSub = Router.routeChangeStart$
.subscribe(
() => {
// hide nav
// show loading indicator
}
)
const onFinishLoadingSub = Router
.routeChangeError$
.merge(Router.routeChangeComplete$)
.subscribe(
() => {
// hide loading indicator
}
)
this.subs = [
onStartLoadingSub,
onFinishLoadingSub
]
},
componentWillUnmount(){
if(!Array.isArray(this.subs)) return;
this.subs.forEach(
sub => sub.unsubscribe()
)
}
})
// 3. appBar/index.js
export default ({
isNavVisible,
isLoading,
children
}) => <nav className={
isNavVisible ? 'app-bar' : 'app-bar app-bar--hidden'
}>
<LoadingIndicator isActive={isLoading} />
{children}
</nav>
答案 1 :(得分:1)
好消息! next.js 6.1.1-canary.2
的新金丝雀版本将支持多重路由器事件监听器。
$ npm i next@canary
Router.events.on('routeChangeStart', (url) => {
console.log('App is changing to: ', url)
})