react-linkifyで一部のリンクをReact RouterのLinkで出力する
はじめに
react-linkifiyはテキスト内のリンクを解析し、有効なリンクに変換してくれるライブラリです。
基本的な使い方
解析したいテキストをLinkify
で囲みます。
<Linkify>
See source code at https://github.com/tasti/react-linkify/.
</Linkify>
たったこれだけでhttps://github.com/tasti/react-linkify/
がリンクに変換されます。
実現したいこと
デフォルトの状態だと解析されたリンクは全てa
タグで囲まれたリンクに変換されますが、それがサイト内のリンクでも遷移時にページがリロードされてしまいます。
これだとあまり良くないUXになってしまうため、サイト内のリンクをa
タグの代わりにReact RouterのLink
でリンクを出力したくなりました。
実装
ソースコード
import React from 'react';
import { Link } from 'react-router-dom';
import Linkify from 'react-linkify';
// content: string (解析するテキスト)
const CustomLinkify = ({ content }) => {
const url = 'https://example.com';
// サイト内のリンクかどうか判定
const componentDecorator = (href, text, key) =>
!text.indexOf(url) ? (
<Link key={key} to={text.replace(url, '')}>
{text}
</Link>
) : (
<a key={key} href={href} target="_blank" rel="noopener noreferrer">
{text}
</a>
);
return <Linkify componentDecorator={componentDecorator}>{content}</Linkify>;
};
export default CustomLinkify;
今回はCustomLinkify
という名前でコンポーネントを作成してみました。
使い方
<CustomLinkify content={content} />
処理の流れ
componentDecorator
関数の中を見ていきます。
!text.indexOf(url)
この条件式はtext
がurl
と前方一致(text.indexOf(url) === 0
)の場合のみtrue
になります。
参考にした記事はこちらです。
例えばhttps://example.com/
やhttps://example.com/user1
のような文字列はtrue
になります。
<Link key={key} to={text.replace(url, '')}>
{text}
</Link>
あとはLink
のpath指定で不要なURLの部分を削除します。
(例: https://example.com/user1
-> /user1
)
<a key={key} href={href} target="_blank" rel="noopener noreferrer">
{text}
</a>
a
タグはこんな感じです。Reactでtarget="_blank"
を指定する場合はrel="noopener noreferrer"
も一緒に書かないと警告が出ます。
以上でサイト内のリンク(url
と前方一致のリンク)のみをLink
で出力できました。
さいごに
何か間違っている記述等あればご指摘いただけると嬉しいです。
Linkify
をカスタマイズする方法についてはこちらを参考にしました。
Discussion