問題が発生する原因再利用可能なコンポーネントを作成したり、styled-componentsのようなライブラリを使ってスタイリングしたりしている際、UI上は問題なく見えても、ブラウザのコンソールに警告が表示されることがあります。これは、ロジックやスタイリング用のプロパティ(prop)が実際のHTML要素に「漏れて」しまったときに発生します。Reactは認識できないカスタム属性を見つけると、間違いではないかと警告を発します。
styled-componentsを使用した典型的な構成を見てみましょう:
import styled from 'styled-components';
const NavItem = styled.a`
color: ${props => (props.isActive ? '#007bff' : '#6c757d')};
`;
// 使用例
const Sidebar = () => (
<NavItem href="/home" isActive={true}>
Home
</NavItem>
);
これがレンダリングされる際、Reactは isActive を <a> タグに直接付与しようとします。isActive は標準的なHTML属性ではないため、次のような警告が表示されます:
Warning: React does not recognize the `isActive` prop on a DOM element...
問題の根本的な原因バージョン16.1以降、ReactはDOM属性に対して厳格になりました。<div> や <button> といった標準的な要素は、id、className、href などの有効なHTML属性のみを受け入れます。それ以外のものを渡すと、data- や aria- という接頭辞が付いていない限り、Reactはそれを間違いだと判断します。
styled-components を使用したり、プロパティをスプレッド({...props})したりすると、ReactはすべてのプロパティをHTMLに書き込もうとします。ブラウザは <a isActive="true"> をどう扱えばよいかわかりません。これは「DOM汚染(DOM pollution)」を引き起こし、数千のノードを持つ大規模なアプリケーションでは、稀にわずかなパフォーマンスのオーバーヘッドが生じることがあります。
最良の解決策:Transient Propsstyled-components(v5.1以降)を使用している場合、最もスマートな解決策は Transient Props です。プロパティ名の先頭にドル記号($)を付けるだけです。これにより、ライブラリはそのプロパティをスタイリングには使用しますが、HTMLがレンダリングされる前に取り除きます。
実装方法:```
import styled from 'styled-components';
// スタイル専用のプロパティには $ 接頭辞を使用する
const NavItem = styled.a color: ${props => (props.$isActive ? 'blue' : 'gray')};;
const Sidebar = () => ( // $ 接頭辞を付けて渡す <NavItem href="/home" $isActive={true}> Home );
`$isActive` に切り替えることで、プロパティはCSSロジック内に留まります。DOMに到達することはないため、HTMLの妥当性が保たれ、コンソールもクリーンな状態になります。
## 代替案:手動によるプロパティのフィルタリングCSS-in-JSライブラリを使用していない場合や、コンポーネントを手動でラップしている場合もあるでしょう。その場合は、分割代入を使用して、カスタムロジックを標準属性から分離します。これにより、有効なプロパティのみが要素に渡されるようになります。
### 例:```
const CustomButton = (props) => {
// isActiveを取り出し、それ以外を 'domProps' にまとめる
const { isActive, children, ...domProps } = props;
return (
<button
{...domProps}
style={{ fontWeight: isActive ? '700' : '400' }}
>
{children}
</button>
);
};
ここでは、isActive はロジックに使用されますが、{...domProps} からは除外されます。そのため、<button> にカスタムプロパティが渡されることはありません。
応用編:'shouldForwardProp' APIプロパティ名を $ 接頭辞付きに簡単に変更できない場合もあります。複雑なコンポーネントの場合、styled-components や Emotion は shouldForwardProp フィルタを提供しています。これにより、どのプロパティをブラウザに渡すかを細かく制御できます。
例:```
import styled from 'styled-components'; import isPropValid from '@emotion/is-prop-valid';
const Container = styled.div.withConfig({
shouldForwardProp: (prop) => isPropValid(prop) && prop !== 'isActive',
}) padding: ${props => props.isActive ? '20px' : '10px'};;
`@emotion/is-prop-valid` ユーティリティは、文字列が標準的なHTML属性かどうかをチェックする軽量(約8KB)なヘルパーです。`prop !== 'isActive'` を追加することで、その特定のプロパティが漏れるのを防ぎます。
## 修正の確認方法
- **コンソールの確認:** ログをクリアしてリフレッシュします。黄色の警告が消えているはずです。
- **DOMの検証:** ブラウザで要素を右クリックし、「検証」を選択します。タグを確認し、`isActive` 属性が付与されていない `<a href="/home">` になっていることを確認します。
- **UIのテスト:** スタイルが正しく機能しているか確認します。`$isActive` を使用した場合は、CSSがその新しい名前を正しく参照していることを確認してください。
## まとめ「React does not recognize prop」という警告は、HTMLを保護するための安全装置にすぎません。素早く修正するには:
- `styled-components` では **Transient Props** (`$propName`) を使用する。
- プロパティを **分割代入** し、カスタムロジックを `...rest` から分離する。
- 高度な自動フィルタリングには **shouldForwardProp** を適用する。

