Next. Js: Router. Push with State

I'm using next.js for rebuilding an app for server side rendering. I have a button that handles a search request.

In the old app, the handler was this one:

search = (event) => {
    event.preventDefault();
    history.push({
        pathname: '/results',
        state: {
            pattern: this.state.searchText,
        }
    });
}

In the results class, I could get the state date with this.props.location.state.pattern.

So now I'm using next.js:

import Router, { withRouter } from 'next/router'

performSearch = (event) => {
    event.preventDefault();
    Router.push({ pathname: '/results', state: { pattern: this.state.searchText } });
};

In the results class, I use

static async getInitialProps({req}) {
    return req.params;
}

I'm not sure if I have to add this to my server.js:

server.get('/results', (req, res) => {
    return app.render(req, res, '/results', req.params)
})

However, the function getInitialProps throws an error because req is undefined. Long text, short question: how to pass state or params to another page without using GET parameters?

5 Answers

In next.js you can pass query parameters like this

Router.push({
    pathname: '/about',
    query: { name: 'Someone' }
})

and then in your next page (here in /about page), retrieve the query via the router props, which needs to be injected to Component by using withRouter.

import { withRouter } from 'next/router'

class About extends React.Component {
  // your Component implementation
  // retrieve them like this
  // this.props.router.query.name
}

export default withRouter(About)
11

If you want 'clean' urls, one way to go about it is to add onClick handler to your link and store required information in context/redux store. It easy to implement if you already have one.

<Link href='...'>
  <a onClick={()=>{dispatch(....)}}>Link<a/>
<Link>
2

If you want your url remain clean, make a small addition to Prithwee Das's answer like below.

Router.push({
    pathname: '/about',
    query: { name: 'Someone' }
}, '/about');

Now you can access props in your component using props

...

const YourComponent = (props) => {
    useEffect(() => {
        console.log(props.router.query.name);
    }, [props.router.query]);

    return (
        <React.Fragment>
            ...
        </React.Fragment>
    );
};

...
2

I don't know whether this supports SSR, but I had to do it as follows to avoid the error cannot read property 'query' of undefined.

This uses useRouter hook to get access to the url, imported as below.

import { useRouter } from 'next/router'

Assume you want to pass data {name:'Someone'} from Component A to Component B.

In Component A,

const router = useRouter();

router.push(
  { pathname: "/path_of_component_b", query: { name: "Someone" } },
  "path_of_component_b"
);

In Component B,

const router = useRouter();

useEffect(() => {
  alert(router.query.name); // Alerts 'Someone'
}, [router.query]);

With the latest version of NextJS we have hooks and in our case useRouter

import { useRouter } from 'next/router'

function ActiveLink({ children, href }) {
  const router = useRouter()

  const handleClick = (e) => {
    e.preventDefault()
    router.push(href)
  }

  return (
    <a href={href} onClick={handleClick}>
      {children}
    </a>
  )
}

export default ActiveLink

and if you want a dynamic root its as simple as putting it in the string params:

<button type="button" onClick={() => router.push('/post/abc')}>
  Click me
</button>
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Alexander Ross

Alexander Ross

Gaming, Esports & Interactive Media Writer

Alexander Ross has covered the video game industry for a decade, writing deep dives on game design, esports tournaments, VR developments, and gaming culture.

Share this article
Twitter Facebook Pinterest