Panda Noir

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

React

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?.show</htmldialogelement>…

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

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

ApolloClient でカスタムフェッチを使う

いっつも書き方を調べてるのでここにメモを残しておく。 import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './App.tsx'; import { ApolloClient, InMemoryCache, ApolloProvider, HttpLink, from, } fr…

シンプルにToastを実装する in react

使い方 使いたい箇所より上のコンポーネントに <ToastProvider> を追加して(↓こんな感じ)、コンポーネント内で const toast = useToast(); で使う感じです。 createRoot(document.getElementById('root')!).render( <ToastProvider> <App /> </ToastProvider> ); const App = () => { const toast = useToast(); re</toastprovider>…

Next.js + Chakra UI で初期描画からダークモードを反映させたい

問題: なにも設定しないと初期描画のときにカラーモードが反映されない demo このように、Chakra UI でなにも設定しないとリロード直後に一瞬ライトモードで表示されます。この記事ではこの問題を解消する方法を紹介します。 tl;dr ColorModeScript を追加す…

ブロックを使うと prevValue を使うフックが書きやすい

小技。 「一時的な変数を useRef で定義したい」といった時に便利なテクニックです。 { const prevValue = useRef(value); useEffect(() => { if (prevValue.current === value) return; // 変化したタイミングで行う処理 prevValue.current = value; }, [va…

@testing-library/react の debug が途中で途切れてしまう問題について

debug の出力には文字数制限があります。それを回避する方法について紹介します。 in short: debug ではなく prettyDOM(baseElement)) を使う const { debug } = render(<HelloWorld />); debug(); ↓ import { prettyDOM } from '@testing-library/react'; const { baseEle</helloworld>…

useRef するとき、Readonly をつけると幸せになれるかもしれない

useRef<Readonly<HTMLElement>>(null) とすれば ref.current.innerHTML = '' などを禁止できる。つまり、setter として ref を使わないという意思表示になる。 まあ、setAttribute とか appendChild は防げないので完璧ではないですが</readonly<htmlelement>

data-attributes に色々渡してみる

const Component = () => <div data-foo={xxx} /> みたいに色々な値を data-attribute に渡してみました。 結果: undefined, null: そもそも追加されない NaN: ワーニングが出る そのほか: 文字列に変換されて値としてセットされる 検証に使ったデモがこちら</div>

React のコールバックrefが呼び出されるタイミングは、コールバックrefの実装によって違う

コールバックrefの実装方法によって ref が渡されるタイミングが異なります。 インライン関数で渡した場合(<element ref={(ref) => {}} />): 再レンダリングされるたびに呼び出される メモ化したり、クラスのメンバーに格納して各レンダリングで同じものを渡した場合: マウント時と</element>…

componentDidMount と componentDidUpdate は同期的に layout と paint の間に実行される (useLayoutEffect と同じ)

(めっちゃ短いけど、ちょいちょい調べるので) useLayoutEffect は componentDidMount や componentDidUpdate と同じフェーズで実行されるということに注意してください 引用元: フック API リファレンス useLayoutEffect 逆に言えば、componentDidMount と c…

Flux Utils のストアをいい感じに hooks で扱う

https://github.com/Fieldscope/flux-hooks を参考にしつつ、型をつけたり型推論が効きやすいように調整したりしてます。 export const useFluxStore = < TStore extends ReduceStore<TState, unknown>, TState = ReturnType<TStore['getState']> >( store: TStore, reducer: (store: TStore) => T</tstore['getstate']></tstate,>…

React でテストしているときに You might have mismatching versions of React and the renderer と出たときの対処法

jest.resetModules() などの関係でこのエラーが出ることがあります。そういうときにごり押すハックを編み出したので紹介します。 jest.mock('react', () => jest.requireActual('react')); それがこちらです。こうすることで jest.resetModules や jest.isol…

高FPSをたたき出すために UncontrolledComponent にしてみたけど、そんなに変わらなかった話

タイトルの通りです。React の再レンダリングを介さずにDOMを直接更新する方が高FPSを出せるか実験してみたけど、そんなに変わらなかったという話です。 ことの発端 ストップウォッチを作っていて、こんな感じの ControlledComponent を書いていました。とて…

React の key をちゃんと使えないと起こる問題

「React の key に配列の添え字を使ってはいけない」理由を説明できますか? リスト以外で key を使うべき場面をご存じですか? 今回は React の key を適切に扱えないと起こる問題を紹介します。 ダメな例のデモ まず、key を適切に設定していない、keyをつけ…

型安全に 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>

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

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

軽量な 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>…

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 イベント…

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

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

esbuild なら React の playground が5秒で出来る!!!!!

esbuild はプラグインなしで JSX・TSXをコンパイルできるから、React のプレイグラウンドがすぐ作れる!! $ npm init --yes $ npm i esbuild react react-dom $ esbuild src/main.tsx --bundle '--define:process.env.NODE_ENV="development"' --outfile=ou…

React.forwardRef でジェネリクスを使いたい

たとえば、以下のようなジェネリクスを使ったコンポーネントを考えます。 <Component<string> prop1="string" prop2="string" ref={ref} /> Component の prop1 と prop2 は同じ T 型とします(上の例では T は string)。 ref がなければカンタンに実装できる ref さえなければ</component<string>…

React ref解説

refとは? refとはReference(参照)のことです。ミュータブルな値を管理するときに使います。 refの使いみちの最たるものはDOMへのアクセスです。たとえばinput要素が持つfocusメソッドを呼びたいときにrefを使います。 const App = () => { const ref = useR…

Reactのリハビリがてらアプリ作った記録

卒業研究とか部活に追われてあまりReactとか触れていなかったのでリハビリのつもりでやった。1日でガーッと書いたときの記録。コケたところとかも(どうせ後でまた同じところでコケるので)記録しておく。 どういうアプリ? graphemesplitという、Unicodeで1文…

そうだ、明日京都行こう。

京 都 行 き た い ! ! ! ! ! …失礼しました。授業で「複数のWeb APIを組み合わせてオリジナルのサービスを作ってみましょう!」という演習があって、それで作ったサービスを公開したので紹介します。 https://pandanoir.net/webcomp 「そうだ、京都行こう」…

JavaScriptの環境構築あれこれ

JavaScriptの環境を構築するのがつらくて辛くて仕方がないのでチートシートを作ることにしました。やや長くなったので目次をつけます。 Webpack関連 WebpackのローダーとBabelの役割分担 Webpackのインストール ts-loader ts-loaderはJSXも扱える vue-loader…

超!体系的に学ぶWebアプリケーション開発

この記事はWebサーバーを建てるところからWebアプリケーションを開発できるようになることを目標としています。 目次 目次 この記事の目標 [超!基本] Webページが表示されるまで HTMLとは? JavaScriptとは? [超!Webサーバー] Webサーバーとは? ファイア…

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

みなさん<dialog>要素を知っていますか?HTML5.2で追加された要素で、モーダルウィンドウをカンタンに実装できるステキ要素です。これをReactから使おうとしてみたのですが、Flux的なやり方ができなくて辛かったです。 …というだけの記事です。 この記事の環境 この</dialog>…