Skip to content Skip to sidebar Skip to footer

React Router BrowserHistory.push Open Link In A New Tab

It is possible to use as to open links in new tab. But is it possible to use browserHistory.push to open links in a new tab?

Solution 1:

React-router is build on the browser History API. browserHistory.push calls pushState() method.

From the first line of the linked document:

pushState( ) takes three parameters: A state object, a title (which is currently ignored), and (optionally) a Uniform Resource Locator (URL).

So, the answer to your question is "No".


Solution 2:

I've been grouching about it for an hour until I saw Cooper's comment

browserHistory is per tab.

which is so simple but accurate, and made me come up with this solution:

I put it in my App.js (UPDATE: I've added the window blur event because I've encountered a missing keyUp event when cmd+tab or cmd+` to another window.)

  const [metaKeyPressed, setMetaKeyPressed] = useState(false);
  const handleMetaKeyDown = e => {
    if (e.metaKey) {
      setMetaKeyPressed(true);
    }
  };

  const handleMetaKeyUp = e => {
    if (e.metaKey) {
      setMetaKeyPressed(false);
    }
  };

  useEffect(() => {
    document.addEventListener('keydown', handleMetaKeyDown);
    document.addEventListener('keyup', handleMetaKeyUp);
    window.addEventListener('blur', handleMetaKeyUp);
    return () => {
      document.removeEventListener('keydown', handleMetaKeyDown);
      document.removeEventListener('keyup', handleMetaKeyUp);
      window.removeEventListener('blur', handleMetaKeyUp);
    };
  });

Then I have metaKeyPressed which I use to select whether to history.push or window.open (simplified for readability):

const handleRoute = path => { 
    if (metaKeyPressed) {
      window.open(path);
    } else {
      history.push(path);
    }
  };

Also, Consider adding a fix for this issue https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/ I haven't not add this because the browser wants the user to explicitly allow popups when I do.


Solution 3:

Building on David's answer, this can be accomplished by wrapping the useHistory hook in a custom one. I renamed mine 'useCtrlHistory' and have this:

import {useEffect, useState} from 'react';
import {useHistory} from "react-router";

export default () => {

  const [ctrlKeyPressed, setCtrlKeyPressed] = useState(false);
  const handleKeyDown = e => {
    if (e.ctrlKey) {
      setCtrlKeyPressed(true);
    }
  };

  const handleKeyUp = e => {
    if (!e.ctrlKey) {
      setCtrlKeyPressed(false);
    }
  };

  const history = useHistory();

  let ctrlHistory = Object.assign({}, history, {
    push: (value) => {
      if (ctrlKeyPressed) {
        window.open(value);
      } else {
        history.push(value);
      }
    }
  });

  useEffect(() => {
    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);
    window.addEventListener('blur', handleKeyUp);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      document.removeEventListener('keyup', handleKeyUp);
      window.removeEventListener('blur', handleKeyUp);
    };
  }, []);

  return ctrlHistory;
};

This will create a new hook that listens for the ctrl key to be pressed. Replace any instances where useHistory.push is present with useCtrlHistory.push and it will detect the ctrl key down.


Solution 4:

Starting with react_router 1.0, the props will be passed onto the anchor tag. You can directly use target="_blank". Discussed here: https://github.com/ReactTraining/react-router/issues/2188


Post a Comment for "React Router BrowserHistory.push Open Link In A New Tab"