Panda Noir

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

forEachの使い方1選

forEachって要らなくない?と思ってたんだけど使い道あるなと気づいたので紹介

nullableなリストに対してループしたい時に使える

nullableList?.forEach(item => {})

これはfor-ofで書こうと思うとちょっとダルい

if(nullableList != null)
  for (const item of nullableList) {}

// あるいは
for (const item of nullableList ?? []) {}

どっちも微妙だ。こういう時はforEachを使うと綺麗に書ける

デスク環境2026

去年のもの→ デスク環境2025 - Panda Noir

デスク全景

デスク全景

横のとこ

ディスプレイ上の小物

デスク周辺機器

  • デスク: FLEXISPOT E8B
  • キーボード: Moonlander
  • マイク: blue Yeti X
  • ウェブカメラ: Elgato Facecam
  • ディスプレイ: ASUS 4Kモニター PA329CV

機器関連は変わらず。今年中に結婚して引っ越しするぞという決意なので、そのタイミングでデスクを新調 + モニターアームを導入したくなってきている(重量的に結構厳しくなってきているので)。

new: 巻取式充電ケーブル

巻取式充電ケーブル

2025年は巻き取り式の充電ケーブルをデスク下に設置した。すこぶる便利。デスクの上に充電ケーブルが散らばらず、ストレスフリー。

使ってるのは TORRAS FlexLine 67W。ただ、これ買った直後に知った Anker Nano Charging Stationがほぼ同じ値段でより多機能なので、今買うならそっちかな…… Nano Charging Station はデスク下に括り付ける運用できなそうなので、そういう意味ではFlexLineで正解なんだけど、ややモヤモヤする…

new: ディスプレイボード

ディスプレイボードに載せた小物

サンワダイレクト ディスプレイボードを買ってモニター上収納を増やした。細々とした小物を全部ここにまとめた。当初は文房具を置くつもりだったんだけど、いざ置くと結構不安定な感じがする+視界に入ってやかましかったのでやめた。

new: 電源タップ

有孔ボード裏の電源タップ

(これ一昨年からやってたかもしれないけど書いてなかったので紹介)

有孔ボードの裏にWindows機と電源タップを置いてある。これも結構便利。電源タップがここにあると、ちょっとだけ使いたい機器をサクッと接続できる。最近は暖房機器とか繋いだりしてる。

まとめ

2025年もそこまで劇的な変化はなく、細かいところがアップデートされた感じ。

今年は 窓なし部屋でも「朝」は作れる。カメラマン×エンジニアが教える『光のデスク設計術』 を読んで自分でもやってみたくなったので、照明周りを整えていきたい。

2025年を振り返る

去年の → 2024年を振り返る - Panda Noir

仕事、趣味、プライベートについて書くぞい。

仕事

  • LINEリニューアルチームに居たんだが、LINEリニューアルが仕切り直しとなったのでまた別のしごとをすることに。
  • 転職活動がつらかった
  • 新しい職場楽しい

記事は1月に書いた1本が300likeを超えた。あと、zennのトータルいいね数が2000を超えた。

関数の多重下請けをやめよう。単一責任の原則と関数の"責任"について

転職活動は、今年1月から本格的に選考を受け始めた。カジュアル面談は去年末から受けたりしてたけど。選考はかなりメンタルをやられて不眠出てきたり、生活リズムぼろぼろになってとても辛かった……最終的には内定がたくさん出て安心したけど、前半は1個も内定出なくてかなり絶望した。転職下手くそ人間。

新しい会社は結構すぐに馴染めてよかった。入社前に一回メンバーとオフラインで顔合わせする機会があったのも大きそう。仕事内容も楽しいしメンバーも自分に似た考え方の人が多いから働きやすい。頑張るぞい。

趣味

  • 前半はとにかく転職で手一杯になっててなにもできてなかった
  • 新しい趣味はそんなに増えてない。強いて言えば1枚刃の髭剃り

合気道をついに完全にやめた。1月から道場に行ってない。地元に戻ったし。

今年は「月1回初挑戦をしよう」という抱負を立てていて、それは達成できた。

  • 1月 ロボットペットの見学会に行く
  • 2月 ヘッドマッサージを受ける
  • 3月 クッキー作りに挑戦する
  • 4月 ラテアートしてみる
  • 5月 瓦割りをする
  • 6月 陶芸する
  • 7月 写経する
  • 8月 競馬場行ってみる
  • 9月 デジタルデトックスしてみる、バッティングセンター行く
  • 10月 垢擦りを受ける、1枚刃の剃刀で髭剃りをする
  • 11月 ヒップホップに入門する
  • 12月 ブレイクダンスに入門する

この中だと剃刀での髭剃りが普通に趣味になった。あとヒップホップを聴こうで聴いたアルバムはずっと聴いてる

プライベート

  • 地元にUターンした
    • 今年一番でかいトピック
    • 仕事部屋を借りたり車買ったり移住支援金を申請したりとか色々やった
  • 婚活
    • 戻って2週間で付き合い始めて1ヶ月で振られた
    • そのあとマッチングアプリで1ヶ月で8人と会ったけどダメだった
    • 12月から相談所を開始。そこそこ順調な滑り出しを見せているので、半年以内には結婚できそう

Uターン、思ってたより全然良かった。車があると新潟良いな。運転も結構すぐにできるようになったし。

婚活についてはあとで個別で記事を出す予定だけど、やってみるとマッチングアプリとはやっぱ性質が結構異なるなと感じる。一言で言えば、外部から付けられる制約が大きく異なってるので、ルールの異なる競技って感じ。

目標の振り返り

  • 外に出る機会を増やす、アウトドアの趣味を増やす
  • 婚活ある程度推し進める
  • 転職を真面目にやる
  • アウトプットを増やす

転職は成功した。婚活は相談所に入ったし佳境かな。あと半年を目処になんとかしたい。 外に出る機会はそこそこ作った気がする。月1回は初挑戦をしようってことで色々やってたし。アウトドアの趣味は増えてないが…アウトプットは記事はできたな。登壇は頑張りたい(新しい職場はそういうの結構活発だし一緒になんかしたい)

来年の目標

ラストマンシップをもつということ の中に出てきた「自分に関係ないことでも、「最後は自分がやるかも」と考える」という部分が全くできていなかったな、と反省したので頑張っていきたい。自分ができる範囲のことだけやるっていう姿勢ではダメだ。仕事の中でラストマンシップを持ちつつチャレンジしていく年にしたい。

useRefの初期値を1回だけ計算したい

useStateは初期値に関数を受け取ると、その関数を初期化時に呼び出してそれ以降は初期化処理を行いません。

const [todos, setTodos] = useState(createInitialTodos); // 初期化コストが高い

対してuseRefは関数を受け取って初期化するという機能がありません。

const todos = useRef(createInitialTodos); // ただの関数のrefという扱いになってしまう

かといって毎回初期値を生成するのは無駄が大きいです。これを回避する方法を思いついたので紹介です

解決策: 初期値をuseMemoで作る

const todos = useRef(useMemo(() => createInitialTodos(), [])); // createInitialTodosは1回のみ呼び出される

このパターンであれば「useMemoはパフォーマンス向上させるときにのみ使うべき」という原則とも合致しています。

dotfilesをサクッとプレビューするためにDockerイメージを作ろう

「他人のdotfilesをちょっと試してみたいけど、環境を汚したくないからやらない」、こういうこと、めっちゃありますよね。僕はあるので進めますね。コレを解消できないかと考えてたんですが、「Dockerイメージをビルドすれば良いじゃん」って気づいたのでやり方の紹介です。

dotfilesをプレビューする

実際にDockerイメージを作ったので、以下のコマンドで僕のdotfilesをプレビューできます↓

docker run -it --rm ghcr.io/pandanoir/dotfiles-preview

DockerイメージをGitHub Actionsでビルドする

GitHubにはコンテナレジストリがあります (ghcr.io)。GH Actionsでここにビルド&プッシュすればGitHubで全部完結させられます。フローはこんな感じ↓

on:
  push:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3 # マルチプラットフォーム向けビルドのためにbuildxをセットアップ
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v6
        with:
          push: true
          file: ./preview.dockerfile
          platforms: linux/amd64,linux/arm64
          tags: ghcr.io/${{ github.repository_owner }}/dotfiles-preview:latest

あとはpreview.dockerfileを書けばOK

# neovimでlanguage serverのインストール時にnpmを使いたいのでnodeイメージを使用
FROM node:24-slim

# 自分の環境で使ってる各種ツールをインストール
RUN apt update && \
    apt install -y zsh git curl fzf unzip gcc && \
    rm -rf /var/lib/apt/lists/*
RUN curl -sS https://starship.rs/install.sh | sh -s -- --yes
RUN curl -fsSL https://deno.land/x/install/install.sh | sh

# 最新ビルドのneovimをインストール
RUN if [ "$(uname -m)" = "x86_64" ]; then ARCH="linux-x86_64"; else ARCH="linux-arm64"; fi && \
    curl -LO https://github.com/neovim/neovim/releases/download/stable/nvim-${ARCH}.tar.gz && \
    tar xzf nvim-${ARCH}.tar.gz && \
    rm nvim-${ARCH}.tar.gz && \
    mkdir -p /root/local && mv nvim-${ARCH} /root/local/nvim

COPY . /root/dotfiles
WORKDIR /root/dotfiles

RUN ./install.sh

CMD ["/bin/zsh"]

おわり

みんなもDockerイメージを作って配布してくれ。いっぱい試したいので。