34

I need to open a link to a new tab after doing some logic.
I have a button like this:

<Button
  onClick={handleSubmit}
>
  Preview
</Button>

with the handleSubmit() being:

const history = useHistory();

const handleSubmit = () => {
  console.log("doing something");
  history.push("/some-link") 
}

As you can see, with my usecase it wouldn't make sense to use the Link component.

So, is there a way to push that link to a new tab, using only history.push()

Yassine Bridi
  • 836
  • 2
  • 10
  • 20

2 Answers2

68

React-router's history is meant to be used just for the navigation of your application and some persistance. I can't see why you need to use it to open a new tab. I think you should use the window object for this.

const handleSubmit = () => {
  console.log("doing something");
  const win = window.open("/some-link", "_blank");
  win.focus();
}

UPDATE: Due to some comments that confirm that it is not neccesary to focus the new window we can make this solution even shorter, like:

const handleSubmit = () => {
  console.log("doing something");
  window.open("/some-link", "_blank");
}
MaCadiz
  • 1,699
  • 9
  • 11
  • I don't know why i limited my self to use only react-router, this would definitely work for me, thanks. – Yassine Bridi Jun 29 '20 at 20:43
  • Did this work? I tried doing this but the context wasn't persisted in the new tab. – Arpit Mar 01 '21 at 17:35
  • @Arpit Worked for me. Didnt use focus. onClick: () => { window.open("/some-link", "_blank"); } – NeERAJ TK Mar 03 '21 at 12:22
  • 1
    @Arpit It's important to note that the context data only exists in the current tab because it is stored in the memory used by it. So if you want to persist that information further than the current tab, you should write code to move that data to the localStorage, persisting it in your backend or something similar – MaCadiz Mar 03 '21 at 14:05
  • 4
    history.push can pass this:----- pathname: '/link', search: value, state: { detail: statevalue }------ but window.open can not. I think so that why this question want to use history.push – Tony Mar 19 '21 at 13:57
  • @Tony yes, you are right. You can use the history object to pass some params to the new URL, but it will only work in the current tab, that's because react router's persistence is within the showing page. If you want to open a new tab, the history object will not be useful, because when you open a new tab all context and state is created from scratch. That's why you need to persist the data using other APIs to achieve the open new tab behavior – MaCadiz Mar 19 '21 at 19:37
  • yes, you're right too, In this case I use window.open,focus pass params and use axios to fetch data in new tab. – Tony Mar 20 '21 at 16:11
  • It's blocked with safari and firefox – Amir Astaneh May 18 '21 at 00:33
  • What do you mean @AmirAstaneh? – MaCadiz May 19 '21 at 21:46
  • @MaCadiz Please test your code on safari and firefox browsers. It's detected as a popup and blocked. – Amir Astaneh May 20 '21 at 00:44
  • 1
    @AmirAstaneh tested it and worked fine. Clean install of firefox and safari on mac – MaCadiz May 20 '21 at 02:23
  • Can anyone clarify the use of `.focus` here? At least for my use case, I see no difference in the behavior with or without it (tested in Chrome and Firefox). My understanding is that with or without the `.focus()` call, a new tab will open and also be navigated to. – regs Feb 02 '22 at 18:54
  • @regs by the time as this answer was posted, some browsers wouldn't focus when using that method. I'm not able to test all major browsers at the time, but I can confirm that for chrome, firefox and edge for desktop is not neccesary. – MaCadiz Feb 07 '22 at 13:23
2

If you simply want to open a new tab without any state transfer, you can just get the path using useHref hook (Docs). This is what the <Link> component internally uses. You can then open it in new tab using window.open. This would automatically add the basename etc for you.

let href = useHref(to);
window.open(href, '_blank');
Divakar Rajesh
  • 1,140
  • 2
  • 18
  • 23