admin管理员组

文章数量:1237551

It is possible to use <link> as

<Link to="route" target="_blank">

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

It is possible to use <link> as

<Link to="route" target="_blank">

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

Share Improve this question asked Jun 23, 2016 at 16:44 KoushaKousha 36.2k59 gold badges186 silver badges313 bronze badges 1
  • 1 browserHistory is per tab. – Cooper Buckingham Commented Jun 23, 2016 at 19:09
Add a ment  | 

4 Answers 4

Reset to default 10

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".

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

browserHistory is per tab.

which is so simple but accurate, and made me e 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./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.

Building on David's answer, this can be acplished 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.

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./ReactTraining/react-router/issues/2188

本文标签: javascriptReact Router browserHistorypush open link in a new tabStack Overflow