Linkについて - React Ariaの実装読むぞ
こんにちは、フロントエンドエンジニアの mehm8128 です。
今日は Link について書いていきます。
useLink
とは
リンクを作るための hook です。
使用例
ドキュメントからそのまま取ってきています。
function Link(props) {
let ref = React.useRef(null);
let { linkProps } = useLink(props, ref);
return (
<a {...linkProps} ref={ref} style={{ color: "var(--blue)" }}>
{props.children}
</a>
);
}
本題
APG はこちらです。
リンクを disabled にする方法
useLink
内部で昨日紹介したusePress
を利用しているのですが、useLink
にisDisabled
を渡すとusePress
内でe.preventDefault()
してくれて、ナビゲーションが発火しないようになります。
これによって disabled が実現されています。
client side navigation
useLink
を用いると、例えば Next.js のrouter.push()
などの client side navigation が a
タグをクリックしたときに実行されるようになります。つまり、Next.js のLink
コンポーネントのような動きをすることになります。
こちらのページに詳細が書かれています。
実現方法としては上記のページに書かれているような方法でRouterProvider
のnavigate
props にrouter.push
などのナビゲーション関数を登録すると、useLink
内部で以下のようにRouterProvider
の context からrouter
を取得しています(このuseRouter
は React Aria 独自のものです)。
そして、useLink
の linkProps
を渡した要素のonClick
でe.preventDefault()
して、router.open()
(navigate
関数の発火などが含まれているメソッド)が実行され、無事 client side navigation が実現されています。
useLink
で足りないもの
色々と面倒を見てくれるuseLink
ですが、どうしても実現できないものもあります。
以下のリンクの「note」を見てください。
Authors are strongly encouraged to use a native host language link element, such as an HTML <A> element with an href attribute. As with other WAI-ARIA widget roles, applying the link role to an element will not cause browsers to enhance the element with standard link behaviors, such as navigation to the link target or context menu actions. When using the link role, providing these features of the element is the author's responsibility.
a
タグのリンクを使うとき、ブラウザはいくつか便利機能を提供してくれています。
例えば Chrome の場合、リンクにホバーしたとき、左下に小さく URL が表示されます。また、リンクの上で右クリックしたときのコンテキストメニューに「新しいタブで開く」などの項目があったり、中クリックしても新しいタブでリンク先のページを開くことができたりします。
しかし、span
タグでリンクを実装してuseLink
を利用した場合、a
タグではないため、ブラウザはこれらの機能を提供してくれません。
以下のページの Example では、リンクがa
タグ以外のタグで実装されています。上で挙げた機能が提供されていないことを確認してみてください。
よって、リンクはできるだけa
タグで実装するのが好ましいです。
リンクがドラッグできないバグ
こんな issue がありました。
普通a
タグはdraggable="false"
がついていない限りドラッグすることができて、ブラウザ上部に持っていくことで別タブで開いたり、テキスト入力欄に持っていくと URL をそのままペースト(?)できたりするのですが、useLink
を使っているとなぜかドラッグできなくなってしまうというバグらしいです。
そこで僕が調査して、一応修正 PR を出すところまでいったのですがまだ見てもらえていません。直ってはいるけど修正のしかたに自信がないので、レビューとかもらえると助かります。
原因としてはusePress
でe.preventDefault()
したくないところでもされてしまっていたので、そこをいい感じに直しました。
まとめ
明日の担当は @mehm8128 さんで、 Text Field についての記事です。お楽しみにー
Discussion