Next.js + Redux императивная маршрутизация (с pkg next-url-prettifier) ​​- проблемы с SSR - PullRequest
0 голосов
/ 11 октября 2018

Я построил этот модуль поверх next-url-prettifier , чтобы включить императивную маршрутизацию (обычно не поддерживается в пакете).Это выглядит так:

const ImperativeRouter = {
  push: (path, query, shallow) => {
    if (typeof window.location !== 'undefined') { // << THIS IS THE ISSUE
      NextRouter.push(
        {
          pathname: `/${path}`,
          query: query
        },
        Router.linkPage(path, query).as,
        { shallow }
      )
    }
  }
}

У меня никогда не было проблем с этим раньше.Вы можете посмотреть эту проблему с github , в которой сопровождающий пакета помог мне выяснить, как заставить его работать.

В настоящее время я работаю над проектом, в котором используется механизм прокруткичтобы вызвать императивные изменения маршрута через Redux, и я получаю сообщение об ошибке:

No router instance found.
You should only use "next/router" inside the client side of your app.

Вот почему я написал в блоке if(<!IS_SSR>) (global var), который я прокомментировал в первом примере кода.

Мой редуктор выглядит так:

...
case TRANSITION_ROUTE: {
      const { prevTrigger, prevRoute, nextRoute } = action.payload
      prevTrigger
        ? ImperativeRouter.push(prevRoute.page, prevRoute.ops || { title: '' }, false)
        : ImperativeRouter.push(nextRoute.page, nextRoute.ops || { title: '' }, false)
      const newState = { ...state }
      newState.transitionDirection = prevTrigger ? BACK : FORWARD
      return IS_SSR ? state : newState
...

У меня настроен следующий шутник:

describe('Router Reducer', () => {
  describe('when invoking an imperative route transition', () => {
    it('can transition to the previous page', () => {
      console.log('IS SSR: ', IS_SSR)
      const payload = {
        prevTrigger: true,
        nextTrigger: false,
        prevRoute: routes[0],
        nextRoute: routes[2]
      }
      if (!IS_SSR) {
        expect(window.location.pathname).toEqual(payload.prevRoute.prettyUrl)
        expect(routerReducer(initialState, { type: TRANSITION_ROUTE, payload })).toEqual({ ...initialState, transitionDirection: BACK })
      } else {
        expect(window.location.pathname).toEqual(routes[1].prettyUrl)
        expect(routerReducer(initialState, { type: TRANSITION_ROUTE, payload })).toEqual(initialState)
      }
    })

    it('can transition to the next page', () => {
      console.log('IS SSR: ', IS_SSR)
      const payload = {
        prevTrigger: false,
        nextTrigger: true,
        prevRoute: routes[0],
        nextRoute: routes[2]
      }
      if (!IS_SSR) {
        expect(window.location.pathname).toEqual(payload.nextRoute.prettyUrl)
        expect(routerReducer(initialState, { type: TRANSITION_ROUTE, payload })).toEqual({ ...initialState, transitionDirection: FORWARD })
      } else {
        expect(window.location.pathname).toEqual(routes[1].prettyUrl)
        expect(routerReducer(initialState, { type: TRANSITION_ROUTE, payload })).toEqual(initialState)
      }
    })
  })
})

... который, я думаю, решит проблемы, как ни странно, первый тест can transition to previous page проходит, а второй тест ...next page - нет.

Журналы тестов выглядят так:

  Router Reducer
    when invoking an imperative route transition
      ✓ can transition to the previous page (2ms)
      ✕ can transition to the next page (4ms)
    upon route transition
      ✓ sets the context for previous & next routes based on current route position in sitemap (1ms)

  ● Router Reducer › when invoking an imperative route transition › can transition to the next page

    expect(received).toEqual(expected)

    Expected value to equal:
      "/work"
    Received:
      "/"

      51 |
      52 |       if (!IS_SSR) {
    > 53 |         expect(window.location.pathname).toEqual(payload.nextRoute.prettyUrl)
      54 |         expect(routerReducer(initialState, { type: TRANSITION_ROUTE, payload })).toEqual({ ...initialState, transitionDirection: FORWARD })
      55 |       } else {
      56 |         expect(window.location.pathname).toEqual(routes[1].prettyUrl)

      at Object.toEqual (__tests__/__redux__/routerReducer.test.js:53:42)

  console.log __tests__/__redux__/routerReducer.test.js:22
    IS SSR:  false

  console.warn server/router/ImperativeRouter.js:21
    can only use next/router on clientside

  console.log __tests__/__redux__/routerReducer.test.js:41
    IS SSR:  false

... показывая, что в то время какглобальная среда, по-видимому, визуализируется на стороне клиента, маршрутизатор, по-видимому, не работает (журнал console.warn server/router/ImperativeRouter.js:21 can only use next/router on clientside), и все просто не ведет себя должным образом, как в случае неудачного теста.

Любые мысли в отношении Интернеталюди

...