Slide 1

Slide 1 text

Synchronous Rendering in React Native GOING OVER THE SPEED LIMIT TAL KOL Head of Mobile Engineering at Wix.com |

Slide 2

Slide 2 text

@koltal Passionate about React Native at Hi.

Slide 3

Slide 3 text

Performance, Are We There Yet? 01

Slide 4

Slide 4 text

The Pepsi Challenge WHICH ONE USES REACT NATIVE?

Slide 5

Slide 5 text

Eliminating the gaps § Animations Declarative animations with Animated + native driver § Navigation Wix react-native-navigation + Airbnb native-navigation § Gestures Krzysztof Magiera’s new native gesture system § Interactions My react-native-interactable library from React Conf

Slide 6

Slide 6 text

Flicker when pushing a new screen 1

Slide 7

Slide 7 text

Flicker when fast scrolling down lists (fill-rate) 2

Slide 8

Slide 8 text

Easy to Fix? APPARENTLY IT’S NOT SO SIMPLE The declarative trick doesn’t work here… An inherent issue with how React works

Slide 9

Slide 9 text

To Block or Not To Block 02

Slide 10

Slide 10 text

The JavaScript Realm The Native Realm The Bridge React Native Architecture JavaScript Thread Main UI Thread

Slide 11

Slide 11 text

Alternative 1: Blocking JavaScript Thread Main UI Thread A A B B

Slide 12

Slide 12 text

Alternative 2: Non-Blocking JavaScript Thread Main UI Thread A A B B

Slide 13

Slide 13 text

React for Web THE CHOICE HAS ALREADY BEEN MADE THEN Similar problem, DOM == native realm Performance gains by non-blocking (shadow DOM)

Slide 14

Slide 14 text

React rendering is asynchronous by design

Slide 15

Slide 15 text

User scrolls N pixels down the list Prepare New Row Scroll Event Create View Redraw Content New uninitialized row drawn as white space New row drawn with correct content React Render

Slide 16

Slide 16 text

Circumventing Asynchronicity 03

Slide 17

Slide 17 text

RCTRootView React Component Tree

Slide 18

Slide 18 text

RCTRootView API § create

Slide 19

Slide 19 text

User pushes a new screen React Root Init Create Event Create Views Create RCTRootView New uninitialized screen drawn as white space New screen drawn with correct content React Render

Slide 20

Slide 20 text

We want to support a synchronous root view

Slide 21

Slide 21 text

RCTSyncRootView React Component Tree

Slide 22

Slide 22 text

RCTSyncRootView API § create § update props

Slide 23

Slide 23 text

User pushes a new screen Create Views Create RCTSyncRootView New screen drawn with correct content React Render JavaScript initialization (load) Magic Store Recipe Magic Use Recipe

Slide 24

Slide 24 text

Synchronous render resolves the flicker!

Slide 25

Slide 25 text

User scrolls N pixels down the list Prepare New Row Scroll Event Create View Redraw Content New uninitialized row drawn as white space New row drawn with correct content React Render

Slide 26

Slide 26 text

User scrolls N pixels down the list Create View Recycle Old Row New row drawn with correct content React Render JavaScript initialization (load) Magic Store Recipe Magic Use Recipe

Slide 27

Slide 27 text

Implementing The Magic Parts 04

Slide 28

Slide 28 text

Hacking the Reconciler TIME TO LOOK UNDER THE HOOD How does React render native views? We’ll use this process to create our recipe!

Slide 29

Slide 29 text

render component

Slide 30

Slide 30 text

Storing the Recipe ON JAVASCRIPT INITIALIZATION Manually call RN.render from SyncRegistry Swizzle UIManager funcs with store stubs

Slide 31

Slide 31 text

render component

Slide 32

Slide 32 text

Using the Recipe WHEN RCTSyncRootView IS CREATED OR UPDATED On demand, execute commands from native Instantiate native views without the bridge!

Slide 33

Slide 33 text

Limitations § Only “declarative” components § No JavaScript code in render func § Prop updates can’t change the tree

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

Proof of Concept Get Full Code github.com/wix/rn-synchronous-render

Slide 36

Slide 36 text

Thanks. linkedin/talkol github.com/talkol @koltal [email protected] medium.com/@talkol @koltal