0
0

More than 1 year has passed since last update.

ActiveLink TypeScript

Last updated at Posted at 2021-10-30

この記事の対象
・TypeScriptで型安全にActiveLinkを使いたい人
・Routerについて知りたい人
・コードを読む練習をしたい人

元々古くからのTechWikiのコードの改良みたいですが。
上の記事で@TK-Cさんが使い方の説明をされています。
本家はGitHubの@remy氏のJavaScriptを参照。

今回はJsのこのコードに型を付けました。

かなり単純かつ簡単で良いコードみたいなので勉強して行ってください。

関数→変数→条件分岐(同値演算子)→returnと言ったシンプルな内容です。

ActiveLink.tsx
import { withRouter, NextRouter  } from 'next/router';
import React, { ReactElement } from 'react';
import Link from 'next/link';

type Props = {
  router: NextRouter;
  children: ReactElement;
  href: string;
  activeClassName: string;
}

const ActiveLink = ({ router, children, ...props }: Props) => {

  let className: string = children.props.className;
  if (router.asPath === props.href) {
    className = `${className} ${props.activeClassName}`;
  }

  return (
    <Link {...props}>{React.cloneElement(children, { className })}</Link>
  );
}

export default withRouter(ActiveLink);

まずは条件分岐を見ます。

router.asPathとprops.hrefが一致するか比較されます。
一致した場合真になりif文の処理であるprops.activeClassNameをclassNameに代入する処理が行われます。

リターン

classNameを返すことによって、activeClassNameとして動くclassNameという2個目の実体を定義することができました。

ルーターの処理

router.pathnameは現在のページをパスとして認識しリンクの判定を識別するものです。
今のページがhrefと一致するならばアクティブリンクが作動するという仕組みです。

Children.onlyは必要なのか?

Children.onlyは子要素を持たない場合に限定する目的で使われるメソッドです。
裏を返せばdom要素で下の階層を持つ場合エラーを返す処理です。
今回の場合Next.jsはActiveLinkでaタグをラップすることになるので不要だと言えます。

childrenにReactElementを付ける理由

ReactElementは依存関係の系列でReactDomに継承させてる他
string | JSXElementConstructorを持ちます。

  • 型について詳しく参考と公式ドキュメントをご覧ください。

もっといい書き方があったら教えてください。

参考

"next": "^12.0.1"
"react": "^17.0.2"
"react-dom": "^17.0.2"
"eslint": "^7.32.0"

実行環境は以上となっています。
もしコードが動かない場合は教えてください。

11月5日追記
論理和を消しました。
trimメソッドを消しました。
if文を修正しました。
論理積を消しました。
Children.onlyのメソッドを変数ごと消しました。
child変数を消しました。
ダイナミックルーティング対応のためrouter.asPathに変更しました。

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