3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【React x Typescript】リンク切れの画像の代替画像を表示する

Last updated at Posted at 2022-01-10

概要

画像がリンク切れの時に表示されるimgコンポーネントってイケてないですよね。
そんな時、画像リンク切れの時は別の画像を表示したいニーズが存在すると思います。

React x Typescriptの組み合わせで微妙にハマってしまったので、整理します。

※なお、リンク切れ時には、例えば以下のように表示されます。

sample_img

環境

$ node -v
v16.13.1

$ npm -v 
8.1.2

実装

ポイントは、currentTarget使用する or onErrorの返り値をany型で明示的に指定してあげることでした。
@YutaUraさんのコメントより、対策法を追加しました!ありがとうございます!

export const App: React.FC = () => {
  const imgPath = 'https://pbs.twimg.com/profile_banners/1353986308062908417/1620745196/1080x360'
  const dummy_img = 'https://pbs.twimg.com/profile_banners/2968069742/1628067771/1500x500'

  return (
    <div className="App">
      <img src={imgPath} alt='sample_img' width='100%' height='auto' onError={(e) => { e.currentTarget.src = dummy_img }} />
      {/* もしくは以下のように記載 */}
      <img src={imgPath} alt='sample_img' width='100%' height='auto' onError={(e: any) => { e.target.src = dummy_img }} />
      
    </div>
  )
}

解説

Reactのimgコンポーネントは、React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>であり、そのonErrorオプションで返却される値の型は、React.SyntheticEvent<HTMLImageElement, Event>です。

この記事を参考に実装してみましたが、どうやらこの型にはsrcは含まれておらず、下記のようなエラーが表示されました。

{/* こうやって書くのはダメだよ */}
<img src={imgPath} alt='sample_img' width='100%' height='auto' onError={(e) => {e.target.src}}/>
エラー文
Property 'src' does not exist on type 'EventTarget'.

色々試行錯誤した結果、上記のサンプルのように、currentTargetを使用するか、返り値eにany型を付けて実装することで、本エラーを回避できます。

余談

Typescriptなのにany使うとは何事だ!と怒られてしまうかもしれません。。。
いいアイデアあれば、コメントいただけると幸いです。

3
3
2

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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?