Panda Noir

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

型安全に React の Provider をマージしてネストを浅くしたい

苦節半年くらいしてようやく実現できてメッチャうれしいので記事も書くぞ!!! Context のネストがつらい React の Context、いくつも書くとなるとネストがどんどん深くなっていってつらいですよね。 <ContextA.Provider> <ContextB.Provider> <ContextC.Provider> <ContextD.Provider> <ContextE.Provider> ... </ContextE.Provider> </ContextD.Provider> </ContextC.Provider> </ContextB.Provider> </contexta.provider>

Apollo server で UUID を取得するサーバーを建てる

Apollo server は別にデータソースをデータベース以外にしても問題ないので、GraphQL API で uuid を取得できるサーバーを建てられる。 const { ApolloServer, gql } = require('apollo-server'); const { v4: uuidv4 } = require('uuid'); const typeDefs =…

T extends unknown が no-unnecessary-type-constraint でできない

TSX のなかでジェネリクスを書くとき、<T> の代わりに <T extends unknown> と書くテクニックは有名ですよね const f = <T>(n: T) => n; // <T> が JSX として認識されてコンパイルできない const g = <T extends unknown>(n: T) => n; // これは OK しかし、 @typescript-eslint/no-unnecessary-type-constr</t></t></t></t></t>…

簡潔な文章を書くコツ

リモートワークの普及でテキストベースのコミュニケーションが増えてきました。簡潔で伝わりやすい文章を書いて同僚と差をつけましょう! なんで簡潔な文章を書くのか? 人間は文章を"読めない"から。 読まれる前提で書いてはいけない。テキストコミュニーケ…

遅延読み込みリストをカンタンに作りたい

React で遅延読み込み機構を作ってみました。 デモ github.com コード useShown と useUpdateHeight という2つのフックを使って実現します。useShown はスクロール状況から「読み込みを開始すべきか」を判定します。useUpdateHeight はコンポーネントの高さ…

Jest でステートを持ったモジュールをテスト毎に初期化したい

private でステートを持ったモジュールのテストをするとき、初期化用のメソッドを作っていませんか? 実は jest では内部ステートをリセットする方法があります。 やり方 やり方は単純で、require('./myModule') でモジュールを読み込み、各テストの前に jest…

zx を使っていい感じに SIGINT を捌く

シェルスクリプトで ctrl + C を押して中断したときのクリーンアップ処理を書くのはそこそこ大変です(頑張ればできますが)。今回は zx を使った、クリーンアップ処理を含むコードの書き方を紹介します。 そもそも zx とは? alt シェルスクリプト的なものです…

pubsub パターンに対する思いと現時点でのベタープラクティス

なんらかの payload を渡したいとき、インターフェイスを定められない。これに尽きる。静的型付けとも相性が悪い。 payload と言ってるのは要するに window.addEventListener(eventName, event => {}) の event のことだ。TypeScript はかなり頑張って型付け…

in-place merge sort を実装してみた

こちらの論文を参考に書きました。 http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=D04E90C1CB92030C1B92452FB9E192A0?doi=10.1.1.22.8523&rep=rep1&type=pdf 実装 さくっと実装をまずお見せします。 const mergeSort = (arr: number[], L = 0, …

lookahead lookbehind(先読み、後読み)まとめ

lookahead (?=pattern) negative lookahead (?!pattern) lookbehind (?<=pattern) negative lookbehind (?) (?<=Promise<)void(?=>) 1年に100回くらい「先読みとあと読みってどっちがどっちだ?どっちがどういう記法だっけ?」って悩むのでほんといい加減にし…

軽量な summary/details を作りたい

detailsを閉じているときに DOM を消しておきたいので作りました(作成時間5分) const Details: VFC<{ summary: ReactNode; detail: () => ReactNode }> = ({ summary, detail, }) => { const [showsDetail, setShowsDetail] = useState(false); return ( <details open={showsDetail} onToggle={() => se</details>…

LINE のコーディングテストを Rust で解いてみた

Rust の練習としてLINEのコーディングをやってみました。以前からずっとやりたかったのですが、問題も長くて面倒でやってなかったんですよね(実際めんどうだった)… 今回解いた問題 以下解説していきます (注: 入出力の例が一切なく、ジャッジシステムも見当…

document.readyState と load, DOMContentLoaded のタイミングについて

結論 complete になると同時に load が発火する(仕様) interactive になったあとかつ complete になる前に DOMContentLoaded が発火する(仕様) 厳密には complete になったあとに load が発火するという仕様です。この前後関係があるため、 readystatechange…

React 18からマウント時にuseEffectが2回呼ばれる訳じゃないよ

結論: 「<StrictMode/> で囲まれてて」「開発ビルドのときだけ」マウント時に useEffect が2回発火するようになります。 あくまで検証が目的の変更 一見、マウント時にcleanupが走るのは無駄に思えますよね?その通りです。2回呼ばれる合理的な理由はありません。 ではな</strictmode/>…

React の lazy をちょっといい感じに書きたい

名前付きエクスポートされているコンポーネントを React で 動的インポートをするには、以下のように書く必要があります。 const MyComponent = lazy(() => import('./Component').then(({ MyComponent }) => ({ default: MyComponent })) ); ただ、ちょっと…

React で touchstart で preventDefault したいとき

touch イベントと mouse イベントの両方に対応したいとき、touchstart 内で preventDefault を呼び出すというテクニックがあります。こうすると、touchstart、touchend のみが発火してそのあとのmousedown、mouseup、click が発火しなくなり、touch イベント…

ここがすごいよMoonlander

Moonlander という分割キーボードを買ったのでレビュー。 ここがすごいよ Moonlander 分割であることはどうでも良くて、Moonlanderはカスタマイズ性がとんでもなく高い。これが最高。しかもカスタマイズの選択肢も豊富。おおよそキーボードに欲しい機能が全…

String Enum に重複がないことを静的型検査で保証する

数値の Enum であればかんたんに重複なく生成できます。 // 0始まりの連番を生成 const [ITEM1, ITEM2, ITEM3] = Array(10).keys(); (この例では ITEM1 などが number になってしまっています。最後にいい感じに型付けする方法をおまけで紹介しています。) …

Puppeteer の await 書きすぎ問題を多少マシにする

immer っぽい API だとうれしいなと思って書いてみました。 元となるコード (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.emulate(iPhone); await page.goto('https://example.com'); await…

E2Eテストに対して思うところ

E2Eテストを本格的にやったことがないのでしてみたいのだが、そもそもいくつか疑問があるのでここでぶちまけておく。 この記事ではwebサイトのE2Eテストを想定しています。他のケースはわかりません 結論 ユーザーの挙動をシミュレートするのは、コストが大…

React v17 からイベントリスナーの張り方変わるけど、breaking changes は抑え気味だよ

touchmove について調べてて気になったので。 React v16 まで React v16 までは、React コンポーネントに張られたイベントリスナーは ドキュメントのルート要素にすべて集約して貼られていました。そのため、React v16 までは、onTouchStart や onTouchMove …

Timers Promises API が最高

名前から既にワクワクするこのAPIは、なんとPromiseを返すsetTimeout、setInterval関数を提供しています!最高です… というわけで今回はそれの紹介です。 基本的な使い方 await setTimeout(1000) ←これができるんです!素晴らしくないですか?? top-level a…

Vite所感

ここ最近 Vite で軽くアプリ作ってたので感想。 Vite とは? 4行で書くと webアプリ開発に特化したビルドツール バンドラではない(バンドル"も"できる) 超高速 dev server & HMR もちろんプロダクションビルドもできる こんな感じ。ビルドツールなので、webp…

【Docker】 fallback 機能付きで静的コンテンツを手軽に配信する

goStatic がオススメ goStaticの特徴はこちらです。 設定ファイル不要 Go言語で書かれている 軽量コンテナ たとえば、以下のコマンド一発で fallback 機能を使いつつ静的コンテンツを配信できます。 docker run -d -p 80:8043 -v $PWD/dist:/srv/http pierre…

git branch を fzf で簡単に選択する in zsh

setopt no_flow_control __fbr() { local item git branch | fzf +s +m -e --ansi --reverse --height 40% | sed -e 's/^ *//' -e 's/^\* //' | while read item; do echo -n "${(q)item} " done local ret=$? echo return $ret } fzf-branch-widget() { LBU…

eslint-plugin-import を使ってディレクトリ単位でアクセス制限を敷く

TypeScript を使っていて、「この関数、他のディレクトリからはアクセスして欲しくないんだけどテストのために export しなきゃ行けないな…」みたいなケースありませんか?実は、ESLint でうまく設定してやると解決できます!今回はその方法を紹介します。 お…

物理キーボードに対するムカつき

最初に書いておきますがただのポエムです。 物理キーボードは Bad UX 物理キーボードは入力はしやすい。が、ctrlキーやaltキーなどを押しても、アルファベットキーたちにインタラクションが何もない。これはBad UX。 逆にソフトウェアキーボードはユーザーア…

オブジェクトのキーの型は PropertyKey 型

Mapped typesを扱う時、よくstring | number | symbolが出てきますよね?実はこれと同じ型が PropertyKeyというビルトイン型であります。 type keys = PropertyKey; // string | number | symbol 実は、これと同じものは keyof any から導出できます。ただ、…

頑張らない正規表現まとめ

はじめに 今回の記事は正規表現についてざっくりとまとめたものです。次のようなことがわかります。 正規表現とはどういったものなのか いつ使うのか 読むにはどうしたらいいのか 逆に、以下については書いていません。 アンカー、先読み、後読み 細かい文法…

1年間まいにち10コミット達成しました!

(本記事はネタ記事です) いやー2020年も終わりですね。みなさんいかがお過ごしでしょうか? 僕は今年1月に「毎日10コミットをする」という抱負を立てていました。そしてなんとこのたび、毎日10コミットを達成しました!! 実際のアカウント 仕事がある日もお…