iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

【React】useMemoとは?

useMemoとは?

useMemoは初回時に実行された関数の値を保持して、次回以降はその保持した値を再利用することでパフォーマンスを向上させる仕組みです。(Swiftでいうところのlazy varとかに近いかな🤔)

使い方

下記のように使うことができます。

  const isSoccer = useMemo<boolean>(() => {
    return sportName === 'soccer' ? true : false
  }, [sportName])

てな感じで本日も以上となります🍺

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

Next.jsとwebpackでのインポートを楽にする

動機

他の階層のモジュールを相対パスでインポートすると、見辛いし、パスが変更した時に書き換えが大変ですよね👀

import Hoge from '../../../components/templates/Hoge'

なので、下記のようにしたい。

import Hoge from '~/components/templates/Hoge'

結論

まずは、next.config.js のwebpackの設定でconfig.resolve.alias['~'] = path.resolve(__dirname)を追加して、モジュールのエイリアス~でアクセスできるようにします.

const path = require('path')

module.exports = {
  webpack(config, options) {
    config.resolve.alias['~'] = path.resolve(__dirname)
    return config
  },
  distDir: '../.next'
}

次にTypeScript側でもPathを解決できるようにtsconfig.jsoncompilerOptionsで下記を追加します。

    "baseUrl": "./",
    "paths": {
      "~/*": [
        "./*"
      ]
    }

これで、下記のように~でモジュールを絶対パスで指定できるようになりました。

import Hoge from '~/components/templates/Hoge'

てな感じで本日も以上となります🍺

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【TypeScript】pngをimportできるようにするぞ

やっていく

src>types内に、index.d.tsというファイルを作りモジュールの型を定義します。ちなみに、d.tsは型定義ファイルと呼ばれ、JavaScriptのライブラリなどをTypeScriptなどで使う際に型情報を付与する目的で使用されます。

declare module '*.png'

あとは、tsconfig.jsoncompilerOptions内に、先ほど追加した型情報ファイルの入ったディレクトを下記のように追加します。

    "typeRoots": [
      "types",
      "node_modules/@types"
    ]

これで、TypeScriptでpngがインポートできるようになりました🍺

import icon from '~/public/images/fidee_icon.png'

てな感じで本日も以上となります🍺

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【React】特定のコンポーネントの外側のタップを検出する

結論

下記のようにして、全体の要素のmousedownイベントを監視して、そのイベントの中のtargetRefに関するイベントのみ除外することで、特定の要素以外の場所がタップされたことを検知することができます👀

  const targetRef: React.RefObject<HTMLDivElement> = React.createRef()

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        targetRef.current &&
        !targetRef.current.contains(event.target as Node)
      ) {
        // Outside tapped!!
      }
    }
    document.addEventListener('mousedown', handleClickOutside)
    return () => {
      document.removeEventListener('mousedown', handleClickOutside)
    }
  }, [targetRef])

  return (
    <div ref={targetRef}>hoge</div>
  )

てな感じで本日も以上となります🍺

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【CSS】overflow-y: visible がスクロールになってしまう

縦方向へのoverflowのみを表示させようと、下記のようにcssを設定していたら、なぜかスクロールできるようになってしまいました。

.container {
  max-width: 100%;
  overflow-x: hidden;
  overflow-y: visible;
}

まさにこんな感じ。

参照: https://stackoverflow.com/q/15970937

解決策

どうやら片方にvisibleを設定し、もう片方にvisible以外の値を設定すると、visible側の設定はautoに変わってしまうバグのようです。

今回は下記のSolutionに倣って、paddingとmarginを相殺させるように設定したら直りました。

stackoverflow.com

修正版:

.container {
  max-width: 100%;
  overflow-x: hidden;
  overflow-y: visible;
  padding-bottom: 250px;
  margin-bottom: -250px;
}

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

Error in render: "ReferenceError: location is not defined" の対処法

SSRするような場合に、下記のように直接locationを参照したらエラーが発生していました。

const hoge = location.pathname == '/hoge'
Error in render: "ReferenceError: location is not defined"

結論

下記のようにブラウザの処理時に、locationにアクセスするようにしたら解決しました。

const pathname = process.browser ? location.pathname : ''

てな感じで本日も以上となります🍺

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com

【React】useEffectとはなんなのか?

useEffectとは?

useEffectは、Reactのコンポーネントレンダリングされた後にフックされる特別な関数です。

毎回呼ばれるの?

公式ドキュメントにも載っているような、下記のシンプルな例の場合では、毎回レンダリング後にuseEffectが呼ばれます。

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

初回レンダリング時や、関数内で使用している値に変更があるレンダリングの時だけ、useEffectを呼び出したい場合は第二引数をそれぞれ設定する必要があります。

まずは、下記が初回レンダリング時のみ実行する例です。

  useEffect(() => {
    document.title = `You clicked ${count} times`
  }, [])

次は、関数内で使用している値に変更があった時だけ実行する例です。

  useEffect(() => {
    document.title = `You clicked ${count} times`
  }, [count])

このように第二引数には、useEffect関数内で依存する値を配列で設定する必要があります。配列を指定しない場合は、無限ループなどに陥る可能性などもあるので、基本的には依存する値を入れておくと良さそうです。

何を返す?

useEffectでは戻り値を設定しなくても問題ないですが、クリーンアップ関数と言って、前回のuseEffectで実行した関数の副作用を消す処理を追加することもできます。一般的には、タイマーのキャンセルやイベントリスナーの削除などに用いられることが多いようです。

てな感じ本日も以上となります🍺

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com