Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
forwardRef を禁止したくて Biome に PR を出した話
Search
Ryuya Yanagi
January 16, 2026
Technology
170
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
forwardRef を禁止したくて Biome に PR を出した話
Ryuya Yanagi
January 16, 2026
More Decks by Ryuya Yanagi
See All by Ryuya Yanagi
XO から Oxlint に移行した話
apple_yagi
0
22
BFCacheを活用して無限スクロールのUX を改善した話
apple_yagi
0
180
最近の推しリンター、Oxlintをご紹介
apple_yagi
0
590
PR_TIMESにおけるFastlyの導入と運用について.pptx.pdf
apple_yagi
1
74
PR TIMESにおけるNext.jsとcacheの付き合い方
apple_yagi
4
3.2k
開発速度を上げつつ品質を保つためのフロントエンド開発
apple_yagi
1
990
Other Decks in Technology
See All in Technology
AI時代のYAGNI:「爆速で無駄になった機能」からの学び / 20260720 Naoki Takahashi
shift_evolve
PRO
3
520
AI時代の開発生産性は、個人技からチーム設計へ
moongift
PRO
4
2.5k
事業成長とAI活用を止めないデータ基盤アーキテクチャの設計思想
hiracky16
0
480
2026年のソフトウェア開発を考える(2026/07版) / Agentic Software Engineering 2026-07 Findy Edition
twada
PRO
24
10k
Network Firewallやっていき!
news_it_enj
0
260
Kaggleで成長するために意識したこと
prgckwb
2
440
AI、CDK と協働する Full TypeScript アプリケーション開発 / Full TypeScript Application with AI and CDK
geekplus_tech
2
480
発表と総括 / Presentations and Summary
ks91
PRO
0
190
第67回コンピュータビジョン勉強会CVPR2026読会前編
tsukamotokenji
0
160
ファミコンでPHPを動かす / PHP on the Famicom
tomzoh
2
600
AIツールを導入しても生産性はあがらない? カオナビが直面した 3つの壁と乗り越え方。/ Overcoming 3 Barriers to AI-Driven Productivity at kaonavi
kaonavi
0
160
AI時代におけるテストの基礎の再定義 / Rethinking the Fundamentals of Testing in the AI Era
mineo_matsuya
13
4.3k
Featured
See All Featured
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
260
From π to Pie charts
rasagy
0
240
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
370
It's Worth the Effort
3n
188
29k
The SEO Collaboration Effect
kristinabergwall1
1
510
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Making Projects Easy
brettharned
120
6.7k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
Exploring anti-patterns in Rails
aemeredith
3
450
Code Review Best Practice
trishagee
74
20k
Tell your own story through comics
letsgokoyo
1
1k
Transcript
forwardRef を禁止したくて Biome に PR を出した話 FE Yatai Talks vol.1
やなぎ PR TIMES フロントエンドエンジニア X:@apple_yagi こう見えて?二児のパパです
みなさん React 19 使ってますか?
Actions 系の hooks の追加 useActionState / useFormStatus / useOptimistic use
API の追加 静的サイト用の新しい DOM API の追加 react-dom/static に prerender / prerenderToNodeStream が追加 React Server Components / Server Actions forwardRef なしで ref を渡せるように変更 <Context.Provider> の代わりに <Context> を Provider としてレンダリングできるよ うに変更 etc.. React 19 の変更点
Actions 系の hooks の追加 useActionState / useFormStatus / useOptimistic use
API の追加 静的サイト用の新しい DOM API の追加 react-dom/static に prerender / prerenderToNodeStream が追加 React Server Components / Server Actions forwardRef なしで ref を渡せるように変更 <Context.Provider> の代わりに <Context> を Provider としてレンダリングできるよ うに変更 etc.. React 19 の変更点
// React v18 import { forwardRef } from "react"; const
MyInput = forwardRef(function MyInput({ placeholder }, ref) { return <input placeholder={placeholder} ref={ref} />; }); // React v19 function MyInput({ placeholder, ref }) { return <input placeholder={placeholder} ref={ref} />; } forwardRef は将来非推奨になる予定だが、まだ @deprecated はついていない 間違えて使う可能性があるので禁止したい forwardRef なしで ref を渡せるように変更
ESLint @eslint-react/no-forward-ref react-x/no-forward-ref Biome noReactForwardRef Oxlint 未対応 jsPlugins を用いて @eslint-react/no-forward-ref
などを 使用することができる forwardRef を禁止する Lint ルール
Biome を使っているプロジェクトで ルールを有効にしてみる
{ "linter": { "enabled": true, "rules": { "recommended": true, "nursery":
{ "noReactForwardRef": "error" } } }, "formatter": { "enabled": true } } noReactForwardRef を有効にする
あれ?エラーにならないな
Biome の内部実装を見てみる
impl Rule for NoReactForwardRef { fn run(ctx: &RuleContext<Self>) -> Self::Signals
{ let node = ctx.query(); let model = ctx.model(); let callee = node.callee().ok()?; let is_react_19 = ctx .get_service::<Option<(Utf8PathBuf, Arc<PackageJson>)>>() .and_then(|manifest| { manifest .as_ref() .map(|(_, package_json)| package_json.matches_dependency("react", ">=19.0.0")) }); if is_react_19 == Some(false) { return None; } is_react_call_api(&callee, model, ReactLibrary::React, "forwardRef").then_some(()) } } noReactForwardRef の内部実装の抜粋
package.json から React のバージョンを取得し、19.0.0 より下であれば None を返し、上であ れば forwardRef を使用しているか判定する
let is_react_19 = ctx .get_service::<Option<(Utf8PathBuf, Arc<PackageJson>)>>() .and_then(|manifest| { manifest .as_ref() .map(|(_, package_json)| package_json.matches_dependency("react", ">=19.0.0")) }); if is_react_19 == Some(false) { return None; } is_react_call_api(&callee, model, ReactLibrary::React, "forwardRef").then_some(()) noReactForwardRef の内部実装の抜粋
なるほど、わい pnpm catalogs 使ってるんやが
"Catalogs" are a workspace feature for defining dependency version ranges
as reusable constants. Constants defined in catalogs can later be referenced in package.json files. https://pnpm.io/catalogs 「カタログ」は、依存関係のバージョン範囲を再利用可能な定数として定義するための ワークスペース機能です。カタログで定義された定数は、後で package.json ファイルか ら参照できます。 by Nani 翻訳 pnpm catalogs とは
package.json に記述する React のバージョンが "catalog:" となるため、正しいバージョン を解決することができない # pnpm-workspace.yaml packages:
- "apps/*" - "packages/*" catalog: react: 19.2.1 react-dom: 19.2.1 # package.json { "devDependencies": { "react": "catalog:", "react-dom": "catalog:" } } pnpm catalogs とは
ちなみにこの問題は ESLint では発生しない
import module from "node:module"; import path from "node:path"; const _require
= module.createRequire(process.cwd() + path.sep); export function getReactVersion(): string { return _require("react").version; } export function create(context: RuleContext<MessageID, []>): RuleListener { // Skip if React version is less than 19.0.0 const version = getReactVersion() if (compare(version, "19.0.0", "<")) { return {}; } return { CallExpression(node) { ... }, }; } no-forward-ref の内部実装のイメージ(ESLint)
module.createRequire を使用して現在の作業ディレクトリ基準の require を作成し、 プロジェクトに入っている React のバージョンを取得する import module from
"node:module"; import path from "node:path"; const _require = module.createRequire(process.cwd() + path.sep); export function getReactVersion(): string { return _require("react").version; } Biome は Rust で実装されているので、この手法が使えず package.json をパースして React の バージョンを取得している React のバージョンの取得方法
この問題を解決するために pnpm-workspace.yaml からバージョンを取得できるようにする Pull Request を出してみた(出してから時間が経ってしまったのでマージされるかは怪しい) https://github.com/biomejs/biome/pull/8396 ただ、最近 yarn と
bun にも catalogs 機能があることに気づいたのでそちらは別途対応が必要 となる yarn catalogs は pnpm catalogs と同じ記法だが、bun catalogs は package.json に catalog を定義する そもそもバージョンの取得方法を根本的に変えた方が良いか? 作業ディレクトリの node_modules の中を探索するとか 有識者の方、ご意見お待ちしております この問題の解決策として
React 19 では forwardRef を書く必要はなくなった 将来非推奨になる予定 ESLint/Biome には forwardRef を禁止する
Lint ルールがある Biome は今のところ pnpm catalogs を解決できない 自分の PR がマージされたら解決するはず まとめ