- 投稿日:2019-01-26T19:22:37+09:00
Reatに入門して1日目の私がつまずいた用語
DOM
Document Object Modelの略
HTMLやXMLの各要素にアクセスする仕組みのこと。JSX
JavaScriptを拡張した言語
Reactを用いて、HTMLを出力するもの。
見た目は、HTMLと似ている。
JSXはアプリケーション内部では、トランスパイルされJavaScriptのコードに変更される。
JSXをJavaScriptにトランスパイルしているのはBabelトランスパイルとは
ある言語で書かれたコードをもとに、別の言語のコードに書き換えること。
なぜJSXを使うのか?
JavaScriptを書くよりも、可読性が高く書きやすい為。
JSXとJavaScriptでHello, World
sample.js// JSXの場合 render() { return <div>Hello, World</div>; } //JavaScriptの場合 render() { return React.returnElement( "div", nul, "Hello, World" ); }JSXの方が書きやすいのは明白。
Webpack
複数のファイルを1つにまとめて、Webに読み込みやすくするもの。
Component
Webサイトを構成する部品のこと。
Reactには2つにComponentがある。
componentは再利用することができる。functional component
関数の定義によって作成するコンポーネント
class component
クラスの定義によって作成するコンポーネント
props
componentの属性
propsには文字列や関数などなんでも使うことができる。
基本的には{}
に囲って属性を渡す。
- 投稿日:2019-01-26T00:04:20+09:00
雰囲気で使わない @types/react
@types/react の型定義を雰囲気で使っている皆さん、こんにちは。React コンポーネントを書くときはどの型を使い、どう書くべきか?という疑問を Twitter でお見かけし、雰囲気で使っていた私も気になったので @types/react の中身を覗いてみました。
master に入り、いよいよリリース間近な Hooks。本稿は FC(旧SFC) の話が前提です。VScode で型付けをしようとすると、似たような型が山ほど出てきて、どれを使うのが適切なのか・違いが何なのか…パッと見分かりませんね。
- ReactNode
- ReactChild
- ReactElement
- StatelessComponent
- FunctionComponent
- JSX.Element
- SFC
- FC
という訳で、こんな Props を持っているコンポーネントの各種書き方を比較、白黒ハッキリさせていきたいと思います。
type Props = { test: 'test' }? Winners
結論からいうと、以下二つのどちらかの書き方が良さそうです。
const MyComponentA: React.FunctionComponent<Props> = props => (<></>) const MyComponentB: React.FC<Props> = props => (<></>)引数の props に型注釈を入れていませんが、これだけで推論はちゃんと動いてくれます。定義元の
React.FunctionComponent
にprops: P & { children?: ReactNode }
が既に入っているので、プログラマー定義のP型type Props = { test: 'test' }
とマージしてくれます。これが勝者たる所以です。React.FC は React.FunctionComponent の定義を参照しているため、全く同じものと言えます。type FC<P = {}> = FunctionComponent<P>;React.FunctionComponent が本流ですが、長ったらしいので、React.FC のほうが自分は好みです。つぎに、残念ながら良くなさそうな書き方を紹介します。
?♀️ children? を自前で入れる必要アリ
基本的に推論に頼りたい派なので、今まで自分はこの書き方をしていました。render children が必要な度、
type Props
にchildren?: ReactNode
を自前で注入しなければならず、やや冗長です。const MyComponentC = (props: Props) => (<></>) const MyComponentD = (props: Props): JSX.Element => (<></>) const MyComponentE = (props: Props): React.ReactElement<any> => (<></>)
MyComponentC
の戻り型推論はJSX.Element
で、JSX
は @types/react の中で切られている namespace です。JSX.Element
は、React.ReactElement
を空継承しています。つまり、この3つの書き方は全く同じであり、後者二つは戻り型注釈付与の意味がない事になります。interface Element extends React.ReactElement<any> { }?♂️ 型が緩い
特に困ることはないですが、
React.ReactElement
を含んだ UnionTypes なので次の書き方でもコンパイルは通ります。ReactNode や ReactChild には、FunctionComponent 以外にも色んな型が UnionTypes で入っており、コンポーネント以外の型へも、制限を緩めてしまっています。ReactText
の実体はstring | number
です。// type ReactChild = ReactElement<any> | ReactText; const MyComponentF = (props: Props): React.ReactChild => (<></>) // type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; const MyComponentG = (props: Props): React.ReactNode => (<></>)こんなコンポーネントを作る人はいないでしょうが、コンパイルエラーを得られていないことから、間違っていることは明らかです。
const MyComponentF = (props: Props): React.ReactChild => (0) const MyComponentG = (props: Props): React.ReactNode => (null)? そもそも deprecated
@deprecated as of recent React versions, function components can no longer be considered 'stateless'. Please use
FunctionComponent
instead. @see React Hooksだそうです。Hooks の影響をもろに受けている…。この書き方をしていたら、気分が向いた時に書き換えましょう。
const MyComponentH: React.StatelessComponent<Props> = props => (<></>) const MyComponentI: React.SFC<Props> = props => (<></>)ちなみに、この二つどちらも
React.FC
と同様に、React.FunctionComponent
のエイリアスでしかないので、定義内容は一緒です。似たような定義山ほどあった理由は、前方互換を担保したりショートハンドを提供するためだった、というお話でした。