Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible to pass state to next/router? #771

Closed
bryan opened this issue Jan 15, 2017 · 44 comments
Closed

Possible to pass state to next/router? #771

bryan opened this issue Jan 15, 2017 · 44 comments

Comments

@bryan
Copy link

bryan commented Jan 15, 2017

With react-router I was able to do:

browserHistory.push({ pathname: "/", state: { message: 'This is a message forwarded in a state.' } })

Is it possible to do something like this using next/router or a way to redirect the user and also pass some value over to the new page?

@arunoda
Copy link
Contributor

arunoda commented Jan 15, 2017

Currently that's not possible and I don't think we'll support it immediate future.

@arunoda
Copy link
Contributor

arunoda commented Jan 15, 2017

But let's open this and see whether we really really need this.

@nkzawa
Copy link
Contributor

nkzawa commented Jan 15, 2017

I think you should do this by passing query parameters.

@bryan
Copy link
Author

bryan commented Jan 16, 2017

I mean you can achieve a similar thing by passing in query parameters like nkzawa said, but I'd rather not pollute my the url with http://www.example.com/?message=This%20is%20a%20long%20message%20forwarded%20to%20be%20displayed and would rather have a state transfer like how react-router does it.

@rauchg
Copy link
Member

rauchg commented Jan 16, 2017

You can use as to disguise the URL

@bryan
Copy link
Author

bryan commented Jan 16, 2017

Well I suppose so, but if I were to use as, the pathname doesn't retain the actual pathname in props.url.pathname, which means more things to pass into the query. It's just cleaner to have it pass the state.

I'm porting over a project to next.js and haven't run into any major compatibility problems since I found ways to refactor codes to make it work, it's just inconvenience and verbosity at this point that can be improved and all this issue is.

Thanks all for your input.

@timneutkens
Copy link
Member

Closing this cause of inactivity 👍

@bryan
Copy link
Author

bryan commented Jan 28, 2018

A little over a year since I brought this up, but is this still not supportable?

@sergiodxa
Copy link
Contributor

You can save any required state in localStorage, sessionStorage, a variable, a Redux store, etc. and then use it in getInitialProps (checking you are running client side).

@egaleme
Copy link

egaleme commented Dec 20, 2018

i think nextjs should start supporting react-router

@vaibhavi3t
Copy link

I want same functionality.

Earlier I was using CRA and there I used to send state to routed component. I wants same functionality with nextjs.

What @sergiodxa suggested in workaround but library support will be good.

@todesstoss
Copy link

Same here, would be great if it will be possible pass data with Router.push() and retrieve it later with withRouter

@namy16
Copy link

namy16 commented Oct 10, 2019

I want same functionality. Any update on this ?

@namlq93
Copy link

namlq93 commented Dec 9, 2019

I want same functionality. Any update on this ?

me too

@allicanseenow
Copy link

Another question related to this issue is:

  • I don't want to pollute my URL when I call the Router.push() and I want to pass a state to the next component. Is there any way to do it? Using localStorage or cookie is a bad practice as they are not directly controlled by React hooks or the old React lifecycle

@abdulhadi1995
Copy link

I have a scenario where I have a clickable component. clicking it would open its details page. With current next.js i can pass the projects id and then get the details using useEffect and axios call but since i already have the data i really wished i could send the state to that page.

@avin-kavish
Copy link

avin-kavish commented Feb 27, 2020

Would be nice to have this.

@sergiodxa Yes, there are many ways to pass temporary messages but the advantage of having it tied to the router is that we don't have to write extra code to manage the life cycle of the values we pass around. They will be tied to router navigation events and unavailable in other contexts.

For example, If I push it to my redux store, then I have to exclude it from being persisted to local storage and also dispatch a clear message action on the receiving end.

If I add it the query string it becomes a perma link that uses can bookmark and later return to.

But it I can push it to the next page and only the next page via router.push I don't have to make any compensations; the value will only be available in that context.

Very similar to connect-flash

@theoludwig
Copy link
Contributor

No solution since Jan 15 2017 ?
We need that feature :

Same here, would be great if it will be possible pass data with Router.push() and retrieve it later with withRouter

@davidebukali
Copy link

Would be nice to have this in nextjs

@azamiya
Copy link

azamiya commented Apr 10, 2020

if you want to hide query params, just use like this

Router.push(`/main?userName=${userName}`, 'main')

than the main page, you can see only /main on url and
console.log(Router.route) shows query

pathname: "/main"
query: {userName: "fadsfasd"}
asPath: "main"

@avin-kavish
Copy link

oh yeah, that's true. Btw I find it really awkward that router requires two strings. react-router works beautifully without, why does this?

@francisrod01
Copy link
Contributor

For those who want to make it, you can use Context Api.

Next.js provides the router.push() passing shallow: true as a prop.
It's the most simple state management to do that.
https://nextjs.org/docs/api-reference/next/router#routerpush

@timneutkens
Copy link
Member

Willing to reconsider this, however it needs a great proposal on how to prevent users from shooting themselves in the foot using history state given you can't access history state server-side for example, it would be very easy to cause hydration issues.

Do note that re-opening this does not mean that I'm not going to write a RFC for this feature, that would be up to the people that want to have this feature.

@myoneflag
Copy link

Router.push({ pathname: '/', query: { message: 'This is a message forwarded in a state.' } }, '/')

@umakantp

This comment has been minimized.

@avin-kavish
Copy link

Router.push({ pathname: '/', query: { message: 'This is a message forwarded in a state.' } }, '/')

This is still not internal state, it's a query string with a mask feature, which is quite an odd thing to do in my opinion.

@pxwee5
Copy link

pxwee5 commented Sep 1, 2020

I'm not super familiar with React ecosystem. But it appears that you can do

router.push(
  { pathname: '/hello-world' }, 
  '/hello-world/2', 
  { step: 2 }
);

When you go back and check before PopState, the option prop will contain { step: 2 }.

We only need this in the router object.

@likerRr
Copy link

likerRr commented Sep 1, 2020

I'm not super familiar with React ecosystem. But it appears that you can do

router.push(
  { pathname: '/hello-world' }, 
  '/hello-world/2', 
  { step: 2 }
);

When you go back and check before PopState, the option prop will contain { step: 2 }.

We only need this in the router object.

It seams like another temporal hack, not intentional behavior. Expected options are listed in the docs. But something similar to this would be great to have as expected behavior

@pxwee5
Copy link

pxwee5 commented Sep 1, 2020

@likerRr Apparently all of the options parameter is being passed to window.history.state. So with my example:
window.history.state == { step: 2 }

@likerRr
Copy link

likerRr commented Sep 1, 2020

@likerRr Apparently all of the options parameter is being passed to window.history.state. So with my example:
window.history.state == { step: 2 }

Seems like it is. Anyway, until it's documented, it can't be used in prod, because implementation of passing options can be changed anytime 😞 Another problem (?) with history state, that it's persistent. And if you play with "back"/"forth" buttons you will mostly get unexpected behavior.

As far as I understand the use case of what community wants is to pass data which will leave only during transition from one page to another and we don't have to bother of clearing it. And this data should not appear again when user clicks "back/forth" in a browser. Otherwise this is the best proposition (imo).

@ken-nah
Copy link

ken-nah commented Sep 3, 2020

Would be nice if next js considered this

@TrongTrinh
Copy link

This worked for me, you can use
#771 (comment)

1: in the Subscription page:
const handleClick = useCallback((mount) => {
Router.push(/payment?mount=${mount}, '/payment');
}, []);
2: in Payment Page
useEffect(() => {
const {
query: { mount },
} = Router;
!mount && Router.push('/campaign-overview/subscription');
console.log('PaymentVM:React.FC -> mount', mount);
}, []);

you can see value of mount in console browser.

@meilechwieder
Copy link

meilechwieder commented Sep 22, 2020

I understand the issue and the convenience of being able to pass along state in router.push.

Would the following be a temporary solution?

Use the browser's history.pushState, as well as a local useState of a location string, and when we want to redirect, we use history.pushState as well as setting a new value to local location state. An update to the location-string-state should trigger a useEffect run. Then have a JS swich statment which evaluates the location and returns components based on the location. And if we wanna get to the same component without history.pushState (for exp. if the user refreshes the page), we can make the location a dynamic next query param. -- did not try it, just trying to think of workarounds.

@meilechwieder
Copy link

meilechwieder commented Sep 23, 2020

For those who want to make it, you can use Context Api.

Next.js provides the router.push() passing shallow: true as a prop.
It's the most simple state management to do that.
https://nextjs.org/docs/api-reference/next/router#routerpush

What if in my in my getServerSideProps, I make two calls, one of which should be redone for every load, and one should only be loaded with a condition. For that, Shallow: true would not help much because its not a state manager, its either redo getServerSideProps, or don't do it at all.
An example of this scenario would be if I make two seperate calls in getServerSideProps. One for the main content of the page and then another call to get the navigation links. In an initial render, I want both calls to be on the server, but then, I already have the nav links in memory so I dont need to refetch them. Thats why we need state.

The only solution is to send along a as option with hidden query params but our code would be awful it for every <Link/> we pass in a bounch of query params that contains our current state. (Actually, as Im writing, Im thinking of making an HOC Link which should go the the specified href and send along a query object with the current state so I wouldnt need to write the state object in each <Linke/>, I'll only handle this in the HOC)

@a-marcel
Copy link

a-marcel commented Dec 3, 2020

Hello,

are there any explanations from the vercel / next team, why it would be problematic to pass a state to the router/link ? It looks like this topic is required by a lot of people (even from me - and i don't see any valid reason against this in this chat).

My usecase is tostore the scroll position (not of the page, the scroll position from an overflow:hidden div), so that a user can go back and have the same position inside this div as before.

I could imaging to have a state property for the NextLink.

<Link ... sate={{ value: 1 }}>LInk that store the State </Link>

This param can be passed to the router push. The next framework is using already the state for their purpose.

I and mostly all in this thread would appreciate if request can be added to the code.

Thanks a lot for all your nice work and the nextjs framework

@rodbs

This comment has been minimized.

@marcin-kochanek

This comment has been minimized.

@timneutkens
Copy link
Member

As said earlier: #771 (comment)

@a-marcel
Copy link

a-marcel commented Dec 9, 2020

Okay, I agree, this is a valid concern.

@meilechwieder
Copy link

Hello,

are there any explanations from the vercel / next team, why it would be problematic to pass a state to the router/link ? It looks like this topic is required by a lot of people (even from me - and i don't see any valid reason against this in this chat).

My usecase is tostore the scroll position (not of the page, the scroll position from an overflow:hidden div), so that a user can go back and have the same position inside this div as before.

I could imaging to have a state property for the NextLink.

<Link ... sate={{ value: 1 }}>LInk that store the State </Link>

This param can be passed to the router push. The next framework is using already the state for their purpose.

I and mostly all in this thread would appreciate if request can be added to the code.

Thanks a lot for all your nice work and the nextjs framework

Actually, you can do it with hidden query params. In nextjs you can redact query params with the as prop on the <link/> component or with the second argument for the router.push method.

@a-marcel
Copy link

a-marcel commented Dec 9, 2020

@meilechwieder : Thanks for this idea. It's not a clean solution but with a dedicated React Link Component (only for this scrolling case) it could work out without creating so much dept.

@sughodke

This comment has been minimized.

@mv29
Copy link

mv29 commented Feb 23, 2021

I am still waiting for this functionality, hope it gets implemented in near future.

@fultonm
Copy link

fultonm commented Mar 25, 2021

Yeah this feature is really needed. The hidden query params work around is nice in the mean time, but we may need to pass complex objects to the next page.

@vercel vercel locked and limited conversation to collaborators Apr 12, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.