Custom React Renderers

<marquee>

@pirelenito

Paulo Ragonha

Tech-lead at Mojang

Yeah, we are using web technologies to build Game UIs.

UI layout engine based on web standards.
It’s similar to a web-browser, but optimized for games.

Β 

React

https://youtu.be/DMza7sGJ-Ro

Building gaming UIs with React

What is a renderer?

import * as React from 'react'
import * as ReactDOM from 'react-dom'

const App = () => {
  return <div>Hello FikaJS</div>
}

ReactDOM.render(<App />, document.getElementById('root'))
import * as React from 'react'
import * as ReactDOM from 'react-dom'

const App = () => {
  return <div>Hello FikaJS</div>
}

ReactDOM.render(<App />, document.getElementById('root'))

react-dom

react-native

React for web

React for native

import React from 'react'

function App() {
  return (
    <div>
      <p>Hello World!</p>
      <p>
        You just use HTML tags.
      </p>
    </div>
  )
}
import React from 'react'
import { Text, View } from 'react-native'

function App() {
  return (
    <View>
      <Text>Hello World!</Text>
      <Text>
        Use native components.
      </Text>
    </View>
  )
}

react

react-dom

react

react-native

React for web

React for native

react

react-dom

React for web

React APIs:

  • React.Component
  • React.Children
  • React.createElement()
  • useState()
  • useEffect()
  • ...

react

react-dom

React for web

  • Does the "heavy work"
  • Calculates the diffing
  • Applies the changes

react

react-dom

React for web

reconciler

DOM hostConfig

  • Does the "heavy work"
  • Calculates the diffing

react

react-dom

React for web

reconciler

DOM hostConfig

  • Applies the changes

react

react-dom

React for web

reconciler

DOM hostConfig

react

react-native

React for native

reconciler

Native hostConfig

react

react-dom

React for web

reconciler

DOM hostConfig

react

react-native

React for native

reconciler

Native hostConfig

react-blessed

<box>First box.</box>

react-three-fiber

<pointLight position={[10, 10, 10]} />

...and many more

Why do we need a custom React render?

react-dom

"...supports all popular browsers, including Internet Explorer 9 and above..."

<marquee>

A renderer that only renders <marquee>

<marquee width="200" height="150" bgColor="#ECBCBC" direction="down" behavior="alternate">
  <marquee behavior="alternate">Fika.JS</marquee>
</marquee>
import * as React from 'react'
import * as ReactDOM from 'react-dom'

const App = () => {
  return (
    <marquee width="200" height="150" bgColor="#ECBCBC" direction="down" behavior="alternate">
      <marquee behavior="alternate">Fika.JS</marquee>
    </marquee>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))
import * as React from 'react'
import * as ReactDOM from 'react-marquee-renderer'

const App = () => {
  return (
    <marquee width="200" height="150" bgColor="#ECBCBC" direction="down" behavior="alternate">
      <marquee behavior="alternate">Fika.JS</marquee>
    </marquee>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

Live coding

➜  me yarn create react-app fika-js-example
yarn create v1.7.0
[1/4] πŸ”  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] πŸ”—  Linking dependencies...
[4/4] πŸ“ƒ  Building fresh packages...

success Installed "create-react-app@3.4.1" with binaries:
      - create-react-app
[####################################################################################################] 100/100

Happy hacking!
✨  Done in 35.30s.
➜  me
yarn create react-app fika-js-example

https://www.npmjs.com/package/react-marquee-renderer

Testing in the wild

react-marquee-renderer

import { render } from 'react-dom'

import { render } from 'react-dom'

import { render } from 'react-marquee-renderer'

What about Minecraft?

Using Gameface

Supports react-dom

We need a sub-set of react-dom

  • 1 "browser" to support (Gameface)
  • Gameface has no inline SVG support
  • Form components are also very limited
  • Subset of props (no data-)
  • ...

Built react-gameface

react

react-gameface

reconciler

hostConfig

~50% faster in Chrome

~8% faster mount

~17% faster in Xbox

Still using DOM APIs

More custom in the future.

Gotchas

One more thing to maintain.

Unstable API of

react-reconciler.

React dev-tools are not suppported

Obscure bugs.

Forgot to implement update for src attribute

Wrapping-up

https://blog.atulr.com/react-custom-renderer-1/

https://youtu.be/CGpMlWVcHok

https://jobs.mojang.com

Thank you!

@pirelenito

Made with Slides.com