Custom Elements#

Use registerElement and createComponent to turn any C# VisualElement subclass into a React component.

Import#

import { registerElement, createComponent } from "onejs-react"

Defining a Custom Element#

Create a C# class that inherits from VisualElement:

using UnityEngine.UIElements;

public class RadialProgress : VisualElement {
    public float progress { get; set; }
    public string trackColor { get; set; }
    public float lineWidth { get; set; } = 4f;
}

Registration#

Register the element once at the top of your entry file. The first argument is a name for the element. The second is the C# constructor via the CS proxy.

registerElement("radial-progress", CS.RadialProgress)

For types inside a namespace:

registerElement("health-bar", CS.MyGame.UI.HealthBar)

Creating a Component#

Use createComponent to get a typed React component:

import type { BaseProps } from "onejs-react"

interface RadialProgressProps extends BaseProps {
    progress?: number
    trackColor?: string
    lineWidth?: number
}

const RadialProgress = createComponent<RadialProgressProps>("radial-progress")

Then use it like any built-in component:

<RadialProgress
    progress={0.75}
    trackColor="#3498db"
    lineWidth={6}
    style={{ width: 100, height: 100 }}
    className="my-progress"
/>

How Props Work#

Standard React props are handled by the reconciler automatically. Everything else is forwarded directly to the C# element as property assignments.

Prop TypeHandled ByExample
styleReconcilerstyle={{ width: 100 }}
classNameReconcilerclassName="my-class"
EventsReconcileronClick={handler}
refReconcilerref={myRef}
Custom propsC# elementprogress={0.75}

Events#

Event handlers work the same as built-in components:

<RadialProgress
    progress={0.5}
    onClick={(e) => console.log("Clicked at", e.x, e.y)}
    onPointerEnter={() => console.log("Hover")}
/>

See Events for the full list of supported event props.

Refs#

Refs point to the underlying C# element:

import { useRef, useEffect } from "react"

function MyComponent() {
    const ref = useRef(null)

    useEffect(() => {
        if (ref.current) {
            console.log(ref.current.GetType().Name) // "RadialProgress"
            ref.current.MarkDirtyRepaint()
        }
    }, [])

    return <RadialProgress ref={ref} progress={0.5} />
}

See Refs for more on working with element references.

Complete Example#

Putting it all together:

import { registerElement, createComponent, render, View, Label } from "onejs-react"
import type { BaseProps } from "onejs-react"
import { useState } from "react"

// Define props
interface HealthBarProps extends BaseProps {
    current?: number
    max?: number
    barColor?: string
}

// Register and create component
registerElement("health-bar", CS.MyGame.UI.HealthBar)
const HealthBar = createComponent<HealthBarProps>("health-bar")

// Use in your app
function PlayerHUD() {
    const [hp, setHp] = useState(80)

    return (
        <View style={{ padding: 16 }}>
            <Label text={`HP: ${hp}/100`} />
            <HealthBar
                current={hp}
                max={100}
                barColor="#e74c3c"
                style={{ width: 200, height: 20 }}
            />
        </View>
    )
}

render(<PlayerHUD />, __root)