9

case 1: Redirected to a new route in the same tab.

<Link to={{ pathname: "/modify_items", state: { foo: "bar" } }} >

When I type console.log(this.props.location.state); the state { foo: "bar" } get printed.

case 2: Redirected to a new route in a new tab.

<Link to={{ pathname: "/modify_items", state: { foo: "bar" } }} target="_blank" >

When I type console.log(this.props.location.state); the state becomes undefined.

My goal is to pass data to a new tab. Please guide me if there is any other way to achieve this in React.js. I just want to pass data to a new tab.

VnoitKumar
  • 1,350
  • 15
  • 29
Abhiz
  • 970
  • 1
  • 16
  • 36
  • Have you reached to a solution? – sçuçu Aug 01 '20 at 18:49
  • I used localstorage @sçuçu for now. But thats not what i wanted.Its working though – Abhiz Aug 04 '20 at 13:09
  • Yes, the localStorage seems like a performant and supported way to do it. I have a few more suggestions with leading links below in my naswer. I hope they can give more ideas. – sçuçu Aug 04 '20 at 19:47

5 Answers5

5

I think this is not possible with Link state. Cause if you leave the page your memory will be clean. You might want to use query or path params if you want to share state over different tabs.

For path params: Get path params in react-router v4

For query variables: Set the Link as followed:

<Link to={{ pathname: '/foo', query: { foo: "bar" } }}/>

and use maybe a library to get the query param. Such as https://www.npmjs.com/package/query-string.

Raoul
  • 311
  • 2
  • 10
3

Since the _blank opens a new tab so it is another instance of your app even the app is the same app the internals are different. But you can use something like localStorage.

Since they will be persisted and will be shared for same origin you will have access to it in the new or any tab or window of your application. You need to query it in the component mount or after first render with and useEffect hook with a second parameter being probably empty array, []. For hooks checkout React docs if you use them.

Another way is to use the querystring. You can receive the query string from your opened comopenent instance.

I am sure you can use any other persistense mechanism, like Indexed DB, Cookies, etc.

There are a few other ways coming into my mind under the umbrella web messaging; Broadcast Channel API, Window.postMessage, and Channel Messaging API that you may make use of.

If you state is relatively small it mifght be good to use querystring, or localStorage is the easiest way to go. If your data way more bigger you can use Indexed DB. It is async. Only be careful when it completes write, then you get it in your new window, tab.

In persistence usage cases, write to persistence before you navigate, just wait the write process if it is async before you navigate (by opening new tab/window in your specific use case).

One might navigate to a new tab maybe by right clicking and selecting from the context menu. ın that case Page Visibility API can be used on the right clicked page in a React effect (attaching its effects in an React effect with an empty second argument to React effect) and the data can be written again to a persistence mechanism, one of above mentioned ones, and the rest I mean the operations in the opening tab will be the same.

Since the writing mechanism can be late and even it is a sync one opening of a new tab if it is not programmatical might happen before the writing is done. In that case the opening tab's React effect to read the data written might be early to read. To circumvent these workarounds like waiting via a setTimeout to read can be used simply, however, a programmatically correct and a guaranteedly timed way would be using one of the appropriate web messaging apis I have mentioned above like Broadcast Channel, postMessage, and Channel Messaging API.

sçuçu
  • 2,960
  • 2
  • 33
  • 60
1

It is not possible to make it via React Router.

But you may use localStorage to save something there before you redirect to new tab and then check if something exists in localStorage on new tab.

Den Kison
  • 1,074
  • 2
  • 13
  • 28
  • The issue in my case is I need tp pass a huge object via state, huge data saving in localstorage is not recomended. – Abhiz Jul 29 '20 at 10:01
  • Is this data accessible via API? – Den Kison Jul 29 '20 at 10:04
  • In case yes you may try to store some id in localStorage and then retrieve data from backend by this id. Or you even may pass with id as query parameter without manipulation with loacalStorage – Den Kison Jul 29 '20 at 10:06
  • saved in local storage and accessed the value. its a successful implementation. still concern is when a big object will get stored there. No cannot access data via api – Abhiz Jul 29 '20 at 11:24
  • It should be possible to store up to 5mb data in localStorage – Den Kison Jul 29 '20 at 11:38
0

If going on new tab it wont work with reat-router! you need to use search param!

  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 25 '23 at 20:37
-1

It's working for me:

<Link to="/onboarding/profile" state={{ from: "occupation" }}>
    Next Step
</Link>

next step:

import { useLocation } from 'react-router-dom'
function Profile () {
    const location = useLocation()
    const { from } = location.state
    return (
      ...
    )
}
keikai
  • 14,085
  • 9
  • 49
  • 68