React 15.5がリリースされ、今までは同梱されていたReact.PropTypes
とReact.createClass
が非推奨となりそれぞれ別パッケージに分かれました。
React.PropTypes
を prop-typesへマイグレーションする方法としてcodemodのスクリプトが提供されています。
React 15.5の警告内容
単純にReact 15.5へアップデートするとReact.PropTypes
とReact.createClass
のコンソールエラーが表示されます。
まだ非推奨の警告だけなので16.0のメジャーアップデートまでは普通に動作します。
Warning: React.createClass is deprecated and will be removed in version 16. Use plain JavaScript classes instead. If you're not yet ready to migrate, create-react-class is available on npm as a drop-in replacement.
や
Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
などの警告がでます。
マイグレーション手順
React.PropTypes
- jscodeshiftをインストール
- react-codemodのマイグレーションスクリプトをローカルにコピー
- jscodeshift + react-codemodでファイルを変換
- prop-typesをnpm install
npm install -g jscodeshift
git clone https://github.com/reactjs/react-codemod.git
# React-PropTypes-to-prop-types.jsのパスをコピーする
# echo `pwd`/react-codemod/transforms/React-PropTypes-to-prop-types.js | pbcopy
# 指定したファイルのPropTypesをjscodeshiftで変換
find src/components -name "*.js" | xargs jscodeshift -t "React-PropTypes-to-prop-types.jsへのパス"
Processing 6 files...
Spawning 3 workers...
Sending 2 files to free worker...
Sending 2 files to free worker...
Sending 2 files to free worker...
All done.
Results:
0 errors
0 unmodified
2 skipped
4 ok
Time elapsed: 3.580seconds
個別にJavaScriptファイルを指定する場合は、次のような感じ。
jscodeshift -t "React-PropTypes-to-prop-types.jsへのパス" "変更したいJavaScriptファイルのパス"
これで自動的に React.PropTypes
を prop-types へ変換してくれます。
後は忘れずにReact 15.5へのアップデートとprop-typesをインストールすれば完了です。
npm i -S react@^15.5 react-dom@^15.5 prop-types
変換に失敗する
TypeError: Cannot read property 'name' of undefined
というエラーがでて変換に失敗する問題は、次のPRで解決されそうです。
- React-PropTypes-to-prop-types.js has a transformation error · Issue #104 · reactjs/react-codemod
- test for existance of "init" property before reading name property by nathanstitt · Pull Request #106 · reactjs/react-codemod
React.createClass
React.createClass
の場合もスクリプトが違うだけ基本的には同じです。
react-codemodのclass.js
を使い、React.createClass
をReact.Component
へ変換します。
$ find src/components -name "*.js" | xargs jscodeshift -t /Users/azu/.ghq/github.com/react/react-codemod/transforms/class.js
Processing 6 files...
Spawning 3 workers...
Sending 2 files to free worker...
Sending 2 files to free worker...
Sending 2 files to free worker...
All done.
Results:
0 errors
1 unmodified
0 skipped
5 ok
Time elapsed: 4.826seconds
React.createClass
の方はオプションもあるので、READMEを読むと良いと思います。
注意点としては、上記のスクリプトはまだProposal段階のtc39/proposal-class-public-fieldsを前提に変換してきます。
そのため、次のようにES2017段階ではパースできないコードが生成されます。
(React.createClass
はauto bindしているため、method = () => {}
でそれを実現するためだと思います)
static propTypes = {
products: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
title: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
quantity: PropTypes.number.isRequired
})).isRequired,
total: PropTypes.string.isRequired,
onCheckoutClicked: PropTypes.func.isRequired
};
これをgetterなどに直すか、BabelのClass properties transformなど使って変換する必要があります。
自分は、babel-preset-stage-2
を入れて解決させました。(+ .babelrc
へ追加)
npm i -D babel-preset-stage-2
その他
codemodにはdouble quoteとかのオプションもありますが、ESLintの--fix
で後からスタイルを揃えました。
変換結果
Alminのalmin/exampleをまとめてReact 15.5へアップデートした結果を次のPRで見ることができます。
9.9割ぐらいはコマンドラインのみでアップデートが完結しました。
Stateless functionがあるファイルの変換が上手くできなかったので手動で変更しました。