0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者の備忘録】モバイル版でもリンクを押下したら別タブは1個だけ開いて、以降はそっちにフォーカスしたい。

Last updated at Posted at 2025-03-17

インデックス

  1. はじめに
  2. 一番シンプルな解決方法
  3. かなり回りくどい解決方法(変わった人向け)
  4. 感想

はじめに

 モバイル版とPC版のどちらでも使うことのできる、「リンクを押下したときに別タブで1個だけ開いて、もう一つ開こうとしたら開いた方のタブにフォーカスする」メソッドについて、2通りの方法を紹介する。達成したい要件としては以下の通りである。

  • リンクが貼られているウェブサイトAがあると仮定する
  • 特にタブがない時にそのリンクを押下すると、別のタブBが開かれる
  • タブBが開かれている時にウェブサイトAからリンクを押下すると、タブBにフォーカスする

 インデックス2の方法を用いるのが一番簡単かつ最適解なのだが、インデックス3のパターンもどこかで使われるかもしれないので、一応書いておく。

 また、次のような構造をしていると仮定する。

......(中略)
    ┣ hogepage/ 
        ┣ App.tsx
......(中略)
    ┣ pages/ 
        ┣ link/ 
            ┣ hogepageLink.tsx
......(中略)

一番シンプルな解決方法

 通常は、以下のように設定すれば問題はない。

App.tsx
......(中略)

type AppProps = {
onClick: () => void;
};

const App = React.FC<AppProps> = ({ onClick, ...props }) => {
......(中略)
return (
<div { ...props }>
......(中略)
<HogepageLink target="hogehoge" onClick={onClick}>HogeHoge<HogepageLink />
......(中略)
</div>
)
};
HogepageLink.tsx
......(中略)
type HogepageLinkProps = StylableProps &
 Omit<LinkProps, 'to'> & {
   children: React.ReactNode;
 };

const HogepageLink: React.FC<HogepageLinkProps> = ({
 className,
 children,
 ...props
}) => (
 <Link to="/hogepage" className={className} {...props}>
   {children}
 </Link>
);

export default styled(HogepageLink)``;

 結論から言えば、この方法を取れば間違いない。/hogepage のハードコードはよろしくないが、あくまで構造を簡潔に書いておきたい感じなので、その点は一旦目を瞑っていただきたい。

かなり回りくどい解決方法(変わった人向け)

 「一番シンプルな解決方法」からかなり遠ざかっているが、一応これでも動作する。ただし、めちゃくちゃ見づらい。メリットがあるとすれば、targetをつけ忘れても機能するという事ではあるが、onClickを指定しようものならこれは機能しなくなるので要注意である。

App.tsx
......(中略)
const App = React.FC = ({ ...props }) => {
......(中略)
return (
<div { ...props }>
......(中略)
<HogepageLink>HogeHoge<HogepageLink />
......(中略)
</div>
)
};
hogepageLink.tsx
 ......(中略)
type HogepageLinkProps = StylableProps &
 Omit<LinkProps, 'to'> & {
   children: React.ReactNode;
 };

const HogepageLink: React.FC<HogepageLinkProps> = ({
 className,
 children,
 ...props
}) => {
 // 無限に新しいタブを開きたくないので、1つ対象のタブが開かれていたらそれにフォーカス
 // 独自にクリックイベントを作っているのでonClickに値を挿入してはいけない
 const hogepageURL = "/hogepage";
 const tabName = 'hogepageTab';

 const handleClick = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
   e.preventDefault();

   const openedTab = window.open('', tabName);
   if (openedTab && !openedTab.closed) {
     openedTab.location.href = hogepageURL;
     openedTab.focus();
   } else {
     const newTab = window.open(hogepageURL, tabName);
     if (newTab) {
       newTab.name = tabName;
     }
   }
 };

 return (
   <a
     href={hogepageURL}
     className={className}
     onClick={handleClick}
     {...props}
   >
     {children}
   </a>
 );
};

export default styled(HogepageLink)``;

感想

 最初は「かなり回りくどい解決方法」の方を採用してやり遂げた気分になっていたのに、よくコードを見渡してみると、「一番シンプルな解決方法」だけで解決してしまったので、なんとも言えない気分になったのを覚えている。仕様の確認は、非常に大事である。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?