如何在nextjs中获取上一个URL

时间:2019-04-08 02:53:48

标签: next.js

如何在nextjs中获取以前的网址? 我认为值this.props.router.asPathnextProps.router.asPath是不同的。

实际上,我想登录后router.push。我知道router.back转到上一页。但是也可以去其他站点。具有历史记录堆栈的用户转到上一页,没有历史记录堆栈的用户转到/主页。

import { Component } from 'react'
import App, { Container } from 'next/app';
import ErrorComponent from '@/components/error'

export default class MyApp extends App {
  render() {
    console.log(this.props)
    const { Component, pageProps, router } = this.props;
    const props = {
      ...pageProps,
      router
    }
    return (
      <ErrorBoundary>
        <Container>
          <Component {...props} />
        </Container>
      </ErrorBoundary>
    );
  }

  componentWillReceiveProps(nextProps) {
    // previous page url /contents
    console.log(this.props.router.asPath) // /about
    console.log(nextProps.router.asPath) // /about
    console.log('window.history.previous.href', window.history.previous) // undefined
  }
}

我该如何解决?或登录后如何获取上一个URL来移动页面?

5 个答案:

答案 0 :(得分:4)

您可以在getServerSideprops或任何其他数据获取方法的上下文中找到Referer(即上一个URL)

context.req.headers.referer  

示例代码

export async function getServerSideProps(context) {
console.log(context.req.headers.referer)
}

答案 1 :(得分:1)

我认为您可以在全局状态下实现自定义历史记录

类似这样的东西

_app.js

import React from 'react';
import App, { Container } from 'next/app';

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    return { pageProps };
  }

  state = {
    history: [] // keep history items in state
  };

  componentDidMount() {
    const { asPath } = this.props.router;

    // lets add initial route to `history`
    this.setState(prevState => ({ history: [...prevState.history, asPath] }));
  }

  componentDidUpdate() {
    const { history } = this.state;
    const { asPath } = this.props.router;

    // if current route (`asPath`) does not equal
    // the latest item in the history,
    // it is changed so lets save it
    if (history[history.length - 1] !== asPath) {
      this.setState(prevState => ({ history: [...prevState.history, asPath] }));
    }
  }

  render() {
    const { Component, pageProps } = this.props;

    return (
      <Container>
        <Component history={this.state.history} {...pageProps} />
      </Container>
    );
  }
}

export default MyApp;

因此,您可以在组件中浏览历史记录中的任何位置

if (!history || !history.length) {
  router.push('/');
} else {
  router.push(history[history.length - 1]);
}

希望这会有所帮助!

答案 2 :(得分:0)

我尝试做类似iurii的回答。我的_app.js看起来像这样(我试图与segment.com集成,因此感到有这种需要)

export default class MyApp extends App {
  componentDidMount () {
    const { asPath } = this.props.router;
    this.setState(prevState => ({ history: [...prevState.history, asPath] }));

    const isBrowser = typeof window !== 'undefined';

    if(isBrowser) {
      // For the first page load
      console.log("Going to log first load --> referrer : ", document.referrer);
      // this can get me the document.referrer properly, if I come to the website from a third party source like google search.
      global.analytics.page(window.location.href,
        {referrer: document.referrer}
      )
    }
  }

  static async getInitialProps ({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return { pageProps }
  }

  state = {
    history: [] // keep history items in state
  };

  componentDidUpdate() {

    const { history } = this.state;
    const { asPath } = this.props.router;





    // if current route (`asPath`) does not equal
    // the latest item in the history,
    // it is changed so lets save it
    if (history[history.length - 1] !== asPath) {

      
      global.analytics.page(window.location.href, {
        referrer: history[history.length - 1] ? history[history.length - 1] : ""
      })
      // this simulates the document.referrer on pages after the user navigates
      this.setState(prevState => ({ history: [...prevState.history, asPath] }));
    }
  }

因此,结合使用history[history.length - 1] ? history[history.length - 1] : ""const isBrowser = typeof window !== 'undefined';,我可以在所有情况下模拟document.referrer。但是我想念一种情况,假设我在google,我的网站目标网页是A,那么A指向B

然后google to A->我得到document.referrergoogle

然后A to B->我得到document.referrerA,与行为一致。

但是现在,如果我刷新页面B,则我的document.referrer再次变为google

我认为我可以将最后一个已知的先前URL保存在本地存储中,但这将是一种反模式,因为浏览器的“后退”按钮可以正确地将用户带到上一页(A),因此数据已经在那里。目前,我可以使用此解决方案,因为我仅将其用于segment.com和google Analytics(分析)目的,因此刷新将使我的分析数据有些混乱,但仍希望有一个完美的解决方案,以便获得准确的数据。

答案 3 :(得分:0)

我已经使用Context做这个

_app.tsx

import { HistoryProvider } from '../contexts/History'

const MyApp: React.FC<AppProps> = ({ Component, pageProps }) => {
  return (
    <ThemeProvider theme={theme}>
      <Header />
        <HistoryProvider>
          <Component {...pageProps} />
        </HistoryProvider>...

/contexts/History.tsx

import { useRouter } from 'next/router'
import React, { createContext, useState, useEffect, useContext } from 'react'

interface HValidation {
  history: string[]
  setHistory(data: string[]): void
  back(): void
}

const HistoryContext = createContext<HValidation>({} as HValidation)
export const HistoryProvider: React.FC = ({ children }) => {
  const { asPath, push, pathname } = useRouter()
  const [history, setHistory] = useState<string[]>([])

  function back() {
    for (let i = history.length - 2; i >= 0; i--) {
      const route = history[i]
      if (!route.includes('#') && route !== pathname) {
        push(route)
        break
      }
    }
  }

  useEffect(() => {
    setHistory(previous => [...previous, asPath])
  }, [asPath])

  return (
    <HistoryContext.Provider
      value={{
        back,
        history,
        setHistory,
      }}
    >
      {children}
    </HistoryContext.Provider>
  )
}

export function useHistory(): HValidation {
  const context = useContext(HistoryContext)
  return context
}

任何组件中,您可以使用

import { useHistory } from '../../contexts/History'

const ContentHeader: React.FC<ContentHeaderProps> = ({ title, hideBack }) => {
    const { history, back } = useHistory() ...

我已使用此组件来备份历史记录,而忽略带有哈希(#)的链接,因为当我不得不将页面滚动到某些页面ID时,本机 router.back()出现了错误。 我想回到最后一页,而不是最后一个锚点

答案 4 :(得分:0)

假设有一个 /profile 页面应该在用户登录时呈现,否则用户应该被重定向到 /login,在用户登录 /login 后,它应该被推送到上一页(此处/profile)但不在其他网站或新标签页上。

  1. /profile 中,您应该如何重定向到 /login
<块引用>

Router.push('/login?referer=profile', '/login')

enter image description here

  1. 在用户成功登录后的/login中,使用:
<块引用>

Router.push(Router.query.referer?.toString||'/')

enter image description here

希望这有帮助。