😝
[React, TS] importしたComponentにonClickを直接書いてみた
Reactでは親から子コンポーネントに関数を渡して実行できます。
import CartIcon from '../components/cart-icon.component'
interface Props {}
const toggleCartHiddenHandler = () => {
...
}
const Header: React.FC<Props> = () => (
<CartIcon onToggle={toggleCartHiddenHandler} />
)
export default Header
疑問に思ったのですが、onClickをimportしたComponentに直接書けば
実行できるんじゃない?と思い試してみたので結果を載せてみます。
修正後のコード
// header.component.tsx
import React from 'react'
import CartIcon from '../components/cart-icon.component'
interface HeaderProps {}
const toggleCartHidden = () => {
...
}
const Header: React.FC<HeaderProps> = () => (
// ここを引数渡しからonClickに
<CartIcon onClick={() => toggleCartHidden()} />
)
export default Header
// cart-icon.component.tsx
import React from 'react'
interface CartIconProps {}
const CartIcon: React.FC<CartIconProps> = () => (
<div></div>
)
export default CartIcon
これをビルドすると、onClickの部分でエラーがでました。
Type '{ onClick: () => toggleCartHidden(); }' is not assignable to type 'IntrinsicAttributes & { children?: ReactNode; }'
Property 'onClick' does not exist on type 'IntrinsicAttributes & { children?: ReactNode; }'. TS2322
{ onClick: () => toggleCartHidden(); }'
は'IntrinsicAttributes & { children?: ReactNode; }'
という型に存在しないぞ、というエラーです。
IntrinsicAttributes & { children?: ReactNode; }とは?
まずですが、これなにかがわかっていませんでした。
調べたところ、React.FC<props>
の、propsの型定義の一部です。
となると
CartIconというComponentに指定したonClick
が、propsの一部としてtsに捉えられてしまったみたいですね。
なのでイベントハンドラは、importしたComponentに直接書くのではなく、 そのComponent内部で書かないといけない、ということですね。
まとめ
1.
ComponentでonClickとかのイベントを実行したいなら、
そのイベント関数をComponentに渡してComponentに実行させる必要がある
Bad
<CartIcon onClick={() => toggleCartHidden()} />
Good(引数として渡す)
<CartIcon onToggle={toggleCartHidden} />
2.
どのComponentがそのイベントを実行するべきなのか、
どのComponentで実行できれば十分なのか考え直すこと
Discussion