Next. Js: Router. Push with State

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
Author

Alexander Ross

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