Skip to content

Instantly share code, notes, and snippets.

@Nkzn
Last active October 15, 2020 06:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nkzn/cd309b7bbb9532d5aa1326637cba6016 to your computer and use it in GitHub Desktop.
Save Nkzn/cd309b7bbb9532d5aa1326637cba6016 to your computer and use it in GitHub Desktop.
ReactDOMとReactNativeのRendererの挙動の違い

React NativeとReact DOMでVDOMの持ち方が違う気がするという話、調べてみたらやっぱりそうでした。

ReactDOMの場合

ReactDOMがReal DOMへの書き込みに使っているcommitUpdateという関数があります。 https://github.com/facebook/react/blob/3d8f465d99ece19238ccb561cdb157d2d676dda4/packages/react-dom/src/client/ReactDOM.js#L716

ReactDOMのほうは辿っていくとReal DOMのElementをゴリゴリ弄っている場所に辿り着けます https://github.com/facebook/react/blob/3d8f465d99ece19238ccb561cdb157d2d676dda4/packages/react-dom/src/client/DOMPropertyOperations.js#L116-L173

ReactNativeの場合

ReactDOMと同じくReact NativeのJS側のRendererにもほぼ同じAPIでcommitUpdateが実装されています。 https://github.com/facebook/react/blob/3d8f465d99ece19238ccb561cdb157d2d676dda4/packages/react-native-renderer/src/ReactNativeFiberRenderer.js#L263

余談ですがこいつもfacebook/reactプロジェクト内なんです

ただし、ReactDOMのそれとは異なり、辿っていっても https://github.com/facebook/react-native/blob/4f886a29a1234c967deae2354bbc5092e0e6595e/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java#L367-L376

ReactShadowNodeという「もう一つのVirtual DOM」を更新して https://github.com/facebook/react-native/blob/4f886a29a1234c967deae2354bbc5092e0e6595e/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java#L307-L322

キューに入れるだけです。 https://github.com/facebook/react-native/blob/4f886a29a1234c967deae2354bbc5092e0e6595e/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyOptimizer.java#L118-L133

キューから取り出された後は https://github.com/facebook/react-native/blob/4f886a29a1234c967deae2354bbc5092e0e6595e/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java#L96

ようやく現実のViewを更新します。 https://github.com/facebook/react-native/blob/4f886a29a1234c967deae2354bbc5092e0e6595e/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java#L117-L127

所感

なんでVDOMを二回も作っているのかというと、きっとスレッド周りの話と無関係ではないのだろうなと思います。

ReactDOMの場合はReactDOM自体がいわばUIスレッドで動いているので、いつElementを触りに行こうが勝手です。

一方で、React NativeはJSの実行スレッドとネイティブUIのスレッドが別々に走っています。何かしらの形で間を埋めなければなりません。

それを解決したのがキューイングだったのでしょう。JSのスレッドからは好きなタイミングでキューに更新指示を突っ込み、UIスレッドはそれを好きなタイミングで拾って更新すればいいのです。

ちょっと腑に落ちないのがReactShadowNodeの存在です。差分管理はReact側で済ませてあるはずなので、わざわざもう一度VDOMを作って管理する必要はないはずなのですが・・・

Yogaでスタイルを実装したVDOMレイヤーがひとつ欲しかったのかな・・・

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment