Skip to main content

ReactAppExt

Trait ReactAppExt 

Source
pub trait ReactAppExt {
    // Required methods
    fn add_react_message<T>(&mut self) -> &mut Self
       where T: ReactPayload,
             for<'a> <T as Event>::Trigger<'a>: Default;
    fn add_react_handler<E, B, M, S>(&mut self, observer: S) -> &mut Self
       where E: ReactPayload,
             for<'a> <E as Event>::Trigger<'a>: Default,
             B: Bundle,
             S: IntoObserverSystem<E, B, M>;
    fn add_react_request<T>(&mut self) -> &mut Self
       where T: ReactRequest;
    fn add_react_request_handler<E, B, M, S>(
        &mut self,
        observer: S,
    ) -> &mut Self
       where E: Event + RequestEvent,
             for<'a> <E as Event>::Trigger<'a>: Default,
             B: Bundle,
             S: IntoObserverSystem<E, B, M>;
    fn add_react_event<E>(&mut self) -> &mut Self
       where E: ReactEvent;
    fn export_react_typescript(&self, path: impl AsRef<Path>) -> Result<()>;
}
Expand description

Registers typed React message payloads on a Bevy App.

Required Methods§

Source

fn add_react_message<T>(&mut self) -> &mut Self
where T: ReactPayload, for<'a> <T as Event>::Trigger<'a>: Default,

Register a typed React message payload without attaching an observer.

After this, an emit(T::NAME, value) from the React app deserializes value into T and triggers it. Prefer add_react_handler unless you want to register the type and observe it separately.

Source

fn add_react_handler<E, B, M, S>(&mut self, observer: S) -> &mut Self
where E: ReactPayload, for<'a> <E as Event>::Trigger<'a>: Default, B: Bundle, S: IntoObserverSystem<E, B, M>,

Register a payload and attach an observer for it in one call.

The payload type is inferred from the observer’s On<T> parameter, so you never name it twice. Call it again with another observer to add more handlers for the same message — registration is idempotent.

app.add_react_handler(|count: On<Count>, mut desired: ResMut<DesiredCubes>| {
    desired.0 = count.event().0;
});
Source

fn add_react_request<T>(&mut self) -> &mut Self
where T: ReactRequest,

Register a typed React request without attaching an observer. Prefer add_react_request_handler.

Source

fn add_react_request_handler<E, B, M, S>(&mut self, observer: S) -> &mut Self
where E: Event + RequestEvent, for<'a> <E as Event>::Trigger<'a>: Default, B: Bundle, S: IntoObserverSystem<E, B, M>,

Register a request and attach its observer in one call.

The request type is inferred from the observer’s On<Request<T>> parameter. The observer answers the request via Request::respond.

app.add_react_request_handler(|req: On<Request<BoardGet>>, board: Res<Board>| {
    req.respond(board.clone());
});
Source

fn add_react_event<E>(&mut self) -> &mut Self
where E: ReactEvent,

Register a Bevy → React event type so it appears in the generated ReactEvents map and bevy.on typing. Sending an event with ReactEvents does not require this, but then the type won’t be known to the exporter.

Source

fn export_react_typescript(&self, path: impl AsRef<Path>) -> Result<()>

Write a self-contained TypeScript module (conventionally src/bevy.ts) mirroring every registered React binding to path.

The generated module covers all three app-messaging surfaces in one pass: a type declaration per payload (mirrored from the #[react_message] / #[react_request] / #[react_event] structs via ts-rs), the ReactMessages/ReactRequests/ReactEvents name→type maps, typed emit/request/on wrappers, and a structured bevy proxy whose nested methods come from dotted request names ("board.get"bevy.board.get()). App code imports that typed surface from ./bevy instead of the untyped functions from "bevy-react", so every call is checked against the same structs Bevy serializes and deserializes.

Keep a single registration site: put your add_react_* calls in a register_bindings(app) function that both the real app (e.g. your plugin’s build) and a small exporter entry point call, so a binding can never exist at runtime without appearing in the generated types. Wire the exporter to a CLI flag that returns before app.run(), commit the output, and have CI regenerate + git diff --exit-code to guarantee the TypeScript never drifts from Rust. (See examples/demos/main.rs and its --export-bindings flag, exposed as npm run bevy:generate.)

if std::env::args().nth(1).as_deref() == Some("--export-bindings") {
    let path = std::env::args().nth(2).expect("output path");
    let mut app = App::new();
    register_bindings(&mut app); // the same fn the real app calls
    app.export_react_typescript(&path)?;
    return;
}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl ReactAppExt for App

Source§

fn add_react_message<T>(&mut self) -> &mut Self
where T: ReactPayload, for<'a> <T as Event>::Trigger<'a>: Default,

Source§

fn add_react_handler<E, B, M, S>(&mut self, observer: S) -> &mut Self
where E: ReactPayload, for<'a> <E as Event>::Trigger<'a>: Default, B: Bundle, S: IntoObserverSystem<E, B, M>,

Source§

fn add_react_request<T>(&mut self) -> &mut Self
where T: ReactRequest,

Source§

fn add_react_request_handler<E, B, M, S>(&mut self, observer: S) -> &mut Self
where E: Event + RequestEvent, for<'a> <E as Event>::Trigger<'a>: Default, B: Bundle, S: IntoObserverSystem<E, B, M>,

Source§

fn add_react_event<E>(&mut self) -> &mut Self
where E: ReactEvent,

Source§

fn export_react_typescript(&self, path: impl AsRef<Path>) -> Result<()>

Implementors§