Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

Reactで<dialog>いじってみたけどつらい件2

www.pandanoir.info

5年経ったので書き直しをば

interface Props {
  isOpen: boolean;
  onClose: () => void;
}

const Dialog = ({ isOpen, onClose }: Props) => {
  const dialogRef = useRef<HTMLDialogElement>(null);
  useEffect(() => {
    if (isOpen) {
      dialogRef.current?.showModal();
    } else {
      dialogRef.current?.close();
    }
  }, [isOpen]);

  return (
    <dialog ref={dialogRef}>
      <form method="dialog">
        name: <input type="text" />
        <br />
        age: <input type="number" />
        <br />
        <button onClick={onClose}>Cancel</button>
        <button>Confirm</button>
      </form>
    </dialog>
  );
};

reactのイベントハンドラーにはasync関数を設定してもよい

意外と知られてないというか、なんかあんまやってる人いない気がしたので

(ちなみに、本当に async 関数が必要なパターンは実は少なくて、ほとんどの場合はアンチパターンなのでやめたほうがよいです。 別の方法で実装できるならそちらにしましょう)

実際にasync関数を設定する例がこちらになります (myConfirm は confirm の promise 版)

const button = () => (
  <button onClick={async () => {
    if (await myConfirm('本当に削除しますか?')) {
      deleteItem();
    }
  }}>
    delete
  </button>
);

こんな感じで、async/await をそのまま設定することもできます。

日報をすぐ書く技術

新卒で入ってからずっと業務の日報を個人的につけてます。日報があると便利なことは多くて、たとえば連休前になにをやっていたのかを思い出したりするときに便利です。

ほぼ毎日日報をつけるには、とにかく書き始めるまでのハードルを下げるのが大事です。僕は memo コマンドを叩くとすぐ日報が書けるようにしています。今回はそのコマンドについて紹介します。

日報を即書ける memo コマンドの仕様

memo コマンドの仕様は以下のとおりです。

  • memo コマンドを叩くと ~/Documents/daily-report/{今年}/{今月}.md が vim で開かれる
  • もし日報ファイルがなければ作成してから vim で開く
  • 日報ファイルを作成する際、 # 2024/06/18(火) のように平日すべての見出しをつくる
  • 開いたとき、今日の見出し位置にカーソルが当たるようにする (さらに、マークもつける)

実際に叩くとこんな感じになります。

memo コマンドの実装

shell command はこんな感じです

memo() {
  local dailyDir="$HOME/Documents/daily-report"
  if [ $# -eq 2 ]; then
    local yyyy=$1
    local mm=$(printf "%02d" $2)
    nvim "$dailyDir/$yyyy/$mm.md"
    return
  fi
  if [ $# -eq 1 ]; then
    local yyyy=$(date +%Y)
    local mm=$(printf "%02d" $1)
    nvim "$dailyDir/$yyyy/$mm.md"
    return
  fi

  local current_daily_file="$dailyDir/$(date +%Y/%m.md)"
  if ! [ -f "$current_daily_file" ]; then
    # 日記ファイルがまだないとき、ファイルを作る
    mkdir -p "$dailyDir/$(date +%Y)"
    node "$dailyDir/create.js" $(date +%-m) >$current_daily_file
  fi

  todays_position="$(cat $current_daily_file | rg "$(date +%Y/%-m/%-d)\(" --line-number | cut -d':' -f1)"
  if [ -z "$todays_position" ]; then
    # なぜか今日の日付が見当たらないときはそのまま開く
    nvim "$current_daily_file"
  else
    # 1. 今日の位置にnマークをつける
    # 1. 昨日の位置にyマークをつける
    # 1. 今日の位置に移動する
    nvim "$current_daily_file" \
      -c "normal ${todays_position}G" \
      -c 'normal mn' \
      -c "/^# $(date +%Y)" \
      -c 'normal my' \
      -c 'let @/=""' \
      -c 'normal `n'
  fi
}

create.js

/**
 * @file 日報を生成するプログラム。
 * node create.js [month] [year]
 * month, year は省略可能。指定しなかった場合、来月の日報が出力される
 */

const today = new Date();

const [
  _command,
  _file,
  month = today.getMonth() + 2,
  year = today.getFullYear(),
] = process.argv;
const date = (d) =>
  new Date(parseInt(year, 10), parseInt(month, 10) - 1, d, 0, 0, 0, 0);

const res = [];
for (let i = 1; i <= 31; i++) {
  const d = date(i);
  if (date(1).getMonth() != d.getMonth()) break;
  if (d.getDay() === 0 || d.getDay() === 6) continue;
  res.push(
    `# ${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}(${
      '日月火水木金土'[d.getDay()]
    })`
  );
}
res.reverse();
console.log(res.join('\n'));