React v15.5(6) and v16
2017/04/14 @koba04
Reactのv15.5がリリースされたので、v15.5での変更点とv16についてのまとめです。
v15.5はバグフィックスとv16での変更点に対する準備なので、可能ならあげておいた方がスムーズにv16がリリースされた時に対応できると思います。
基本的には、v16で色々と廃止するための警告が主になります。 最近のバージョンと同様に、コアから必要なもの以外をどんどん削ぎ落としていく流れです。
この警告に対応するために、Enzymeなどでは利用するために必要なライブラリーが変更されているので更新する際には注意が必要です。
また、当初の予定ではv15.5がv15系の最後のリリースになる予定でしたが、上記のような混乱もあったためフォローアップとしてv15.6もリリースされることになりました。 なので、v15.6がリリースされてから対応するのもアリだと思います。
廃止されるものは色々ありますが、基本的に全てのものに対してマイグレーションのパスは提供されているので対応可能だと思います。 ただ、アクティブにメンテされていないくて15.5対応版をリリースしていないライブラリーを使っていると色々警告が出ると思います。 場合によっては、その警告によってテストが壊れることがあるかもしれません。
Deprecated React.createClass
廃止されること自体は前から言われていたので、使わないようにしていた人も多いと思いますが、create-react-class
として別パッケージとなり、v16ではreact
から削除されます。
import createReactClass from 'create-react-class';
そのためv15.5では、React.createClass
を使おうとすると警告が出ます。
自分の書いたコードでReact.createClass
を使っている場合は、React.Component
を使ったComponent定義かStateless Functional Componentsに書き換える必要があります。
mixinを使っているなど、どうしてもReact.createClass
を使いたい場合はcreate-react-class
を使うこともできますが、可能な限りReact本体が提供する方法を利用する方がいいと思います。
React.createClass
からReact.Component
の定義に書き換えるcodemodも提供されているので、使ってみるのもいいかもしれません。
このcodemodでは、React.createClass
が提供するautobindを実現するために、property initializerのシンタックスを利用します。そのため、変換後はbabel-plugin-transform-class-properties
を使用する必要があります。(Stage 2)
v16になった時点でReact.createClass
を使っているライブラリーを利用している場合には、PR送って対応してもらうか、React.createClass
にcreate-react-class
を代入するなどの対応が必要になるかもしれません。
(v15.5では、警告を出すためにReact.createClass
にはObject.defineProperty
でgetterが設定されており、configurable
でないので置き換えることはできません)
Deprecated React.PropTypes
これも、React.createClass
と同様にずっと言われていましたが、prop-types
として別パッケージとなり、v16ではreact
から削除されます。
import PropTypes from 'prop-types';
そのためv15.5では、React.PropTypes
を使おうとすると警告が出るようになりました。
これもcodemodが提供されているので、それを使って一括で変換することができます。
PropTypesに関しては、FlowやTypeScriptへの移行が勧められているもののハードルもあるので、別パッケージ化されたprop-types
をしばらく使い続けるのは選択肢としてあるのかなと思います。
今回別パッケージとなったのは組み込みのPropTypesのvalidationロジックであり、PropTypesのチェック機構自体がなくなることは、まだ予定されていないので。
ちなみに、将来的にAPIの変更が予定されているContextを使う場合にも、変わらずprop-types
を使って指定します。
(実際にはcontextTypes
の定義でマスクしているだけなので、prop-types
を使う必要はないのですが)
Deprecated Addons
React本体がアドオンとして提供していた諸々が、廃止されたり別パッケージ化したり、移動したりしています。
v16では、react-with-addons
のUMDビルドも提供されなくなります。
react-addons-create-fragment
は、v16のFiber化により配列を返すことができるようになるため、多くの場面で不要となるので削除されます。react-addons-css-transition-group
とreact-addons-transition-group
は、react-transition-group
の別パッケージになりました。CSSTransitionGroup
とTransitionGroup
して利用できます。ただし、全く実装が一緒というわけではないので移行する際には注意が必要です。すでに修正済みですが下記のようなバグとかもあったりするので...。react-addons-linked-state-mixin
とreact-linked-input
は、明示的にvalue
とonChange
を指定すればいいので削除されます。react-addons-pure-render-mixin
とreact-addons-shallow-compare
は、React.PureComponent
を代わりに利用できます。react-addons-update
はimmutability-helper
が代わりに利用できます。
react-addons-test-utils
は、react-dom
のrendererに依存している部分が多いため、react-dom/test-utils
に移動されました。
import TestUtils from 'react-dom/test-utils';
ShallowRenderに関してはreact-dom
に依存していないため、react-test-renderer/shallow
に移動されました。
ちなみにreact-test-renderer
はJestがsnapshot testingで使っていたりする、ReactElementをJSONとして返すrendererです。
ShallowRenderは、これのトップレベルのComponentまでしかrenderしない版として考えることができます。
import {createRenderer} from 'react-test-renderer/shallow';
~~react-addons-perf
だけは、特に何もなくこのままですが、react-addons-perf
は同期的なrenderが前提となっているため、将来的にFiberで非同期的なrenderをする場合には正しく計測できません。~~
[修正] react-addons-perf
は同期的なrenderが前提となっていてFiberへの対応が難しいため、v16(Fiber)への対応は行われません。
Perfに変わる何かについては検討されるので、将来的に何か提供される可能性もありますが、とりあえずは?react_perf
によるBrowser Timelineを使った計測が推奨されています。
15.6(予定)
https://github.com/facebook/react/issues/9398
React.DOM.{p, div,...}
として提供されていたファクトリ関数が廃止となります。- APIの廃止などの警告は、これまでは
console.error
として出力されていましたが、console.warn
で出力されるようになります。
16に向けて
v16はすでに@next
でインストールできます。
そのため、まだ実装されていないサーバーサイドレンダリングとShallowRenderを使っていない部分では試すことが可能です。
npm i react@next react-dom@next
Fiber
v16の一番大きな目玉は、Fiberに内部実装が置き換えられることです。
ただし、v16の時点ではFiberは現在のStackのrendererと互換性のあるモードで動作します。
そのため、Fiberの特徴であるrequestIdleCallback
によってスケジューリングされた非同期なrenderではなく、同期的なrenderとなるため、利用者として大きな違いは感じないかもしれません。
(call stack見ると全く変わっていることがわかると思いますが)
文字列や配列をComponentでラップすることなく直接返すことができるのは嬉しい部分かもしれません。
const Text = ({text}) => text;
const List = () => [1, 2, 3];
ちなみに、v16の時点でもReactDOM.unstable_deferredUpdates
を使うことで、非同期なrenderが出来るようにはなりそうです。
あとは、ReactDOMFiber.js
にあるuseSyncScheduling
というフラグを無理やりfalse
にすればデフォルトで非同期なrenderになります。(軽く試した感じだと問題なく動いていた)
非同期のrenderをどのようにユーザー側のAPIとして見せるのかは、まだ明らかになっていなくてこれから議論していくようです。
Fiberについては、下記に集めたリソースを読むとわかると思います。(今後紹介的な何かを書くかも)
最初に見るものとしてのおすすめは、Lin ClarkによるA Cartoon Intro to Fiber(React.js Conf 2017)です。
互換モードによるFiber自体はfacebook.comでも問題なく動作しているようです。 ただし、サーバーサイドレンダリングに対する対応は、まだ全く入っておらず今後どうなっていくのかは不明です。FiberになるとStreaming renderingもやりやすくなるのではとは思いますが。
No more direct import!
v16からは、それぞれのエントリーポイントがRollupを使ってバンドルされたものになります。 なので下のような構造になります。
react@next and react-dom@next are flat bundles! 👀 #reactjs pic.twitter.com/5ezjjf08sd
— Toru Kobayashi (@koba04) April 7, 2017
これにより、初期ロード時間の短縮やサーバーサイドでのパフォーマンスの向上が見込まれています。 また、利用者側には関係ないですがビルド周りが見直されており、GruntやgulpやBrowserifyのタスクがリポジトリから削除されています。すっきり。
この変更による、一番大きな影響はreact/lib/xxxx
として直接Reactの内部ライブラリを利用しているライブラリが動作しなくなることです。
enzyme
などのメジャーなライブラリはReact側でもケアされていますが、それ以外のライブラリーは壊れてどうにもならなくなることがあるかもしれません。
したがって、そのようなハックをしているライブラリーを利用している場合は注意した方がよさそうです。
リリース?
ちなみにv16は、夏くらい(?)をターゲットに考えているようです。
また何か動きがあれば追記するかも。