react-use-reflisted
Install: claude install-skill ncaq/konoka
# useRefの使用を避ける
`useRef`は命令的なコードになりやすく、
Reactの宣言的なモデルと相性がよくありません。
使う前に代替手段がないか検討してください。
## なぜuseRefを避けたいのか
- `ref.current`はミュータブルであり、レンダリングサイクルと同期しません。値の変更がUIに反映されず、予期しない挙動を起こしやすいです
- 命令的なDOM操作はReactの状態管理と二重管理になりやすいです
- テストが難しくなります。DOMの状態をテストするにはDOMのセットアップが必要になります
- コンポーネントの再利用性が下がります。DOM構造に依存したロジックは別の場所で使い回しにくいです
- `ref.current`への代入は「いつ読んでも最新」という暗黙の前提に依存しており、データフローが追いにくくなります
## 代替手段の検討
### HTML標準の機能を使う
ブラウザが提供する宣言的なHTML要素や属性で解決できないか、
まず検討��てください。
```tsx
// Bad: useRefで開閉を命令的に管理
const detailsRef = useRef<HTMLDetailsElement>(null);
const toggle = () => {
if (detailsRef.current) {
detailsRef.current.open = !detailsRef.current.open;
}
};
// Good: HTML標準の<details>要素なら宣言的に開閉できる
<details>
<summary>詳細を表示</summary>
<p>ここに詳細が表示されます。</p>
</details>;
```
```tsx
// Bad: useRefでポップオーバーの表示を命令的に管理
const popoverRef = useRef<HTMLDivElement>(null);
const showPopover = () => popoverRef.current?.showPopover();
// Good: popover属性とpopoverTargetで宣言的に表現
<button popoverTarget="my-popover">開く</button>
<div id="my-popover" popover="auto">ポップオーバーの内容</div>
```
`<details>`、`<dialog>`、`popover`属性、`<input type="date">`など、
以前はJavaScriptが必要だった機能の多くが現在はHTML標準で提供されています。
### 宣言的なライブラリを使う
DOM操作を抽象化してくれるライブラリがあれば、
そちらを優先してください。
```tsx
// Bad: useRefとuseEffectでIntersectionObserverを管理
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
setIsVisible(entry.isIntersecting);
});
if (ref.current) observer.observe(ref.curr