What I Learned Wrapping a Model Engine as a React Component

When I integrated a third-party model engine into a React project, my first concern was not whether it could render. My concern was where to draw the boundary.
A model engine usually has its own lifecycle, events, controller, resource loading, and internal state. React has its own component state, rendering rhythm, and data flow. If I expose the engine object directly to the page, it may work in the short term, but it becomes hard to maintain.
A Canvas Is Not a Normal Component
Most frontend components can let React own their state. A model canvas is different.
Engine initialization, model loading, view control, component selection, property reading, and teardown behave more like an external runtime. React can place it inside the page, but it should not pretend the engine is only a controlled input.
So I treat the canvas as a boundary component. Configuration and callbacks come from the outside. The engine instance and lifecycle stay inside. The page does not need to know every low-level API. It only uses the capabilities exposed by the component.
The Tree and Property Panel Are Business UI
After a model engine is integrated, the user-facing value often comes from the model tree, property panel, progress indicator, and operation area around the canvas.
The model tree has to synchronize with selection. The property panel follows the current component. Loading state tells the user the system is still working. These look like UI details, but they translate low-level model capability into business interface.
I prefer to package these pieces into a viewer instead of letting every page assemble the canvas, tree, and property panel separately. Otherwise every integration repeats the same coordination problems.
Controller Exposure Should Be Restrained
When wrapping an SDK, it is tempting to expose every low-level method. That looks flexible, but it makes callers depend more and more on engine internals.
I prefer exposing stable operations: load a model, select an element, read properties, switch view, listen to events. Temporary methods and complex engine objects stay inside the component as much as possible.
This sacrifices some freedom, but it creates a clearer maintenance boundary. If the engine upgrades or the API changes later, the impact is smaller.
Wrapping Does Not Erase Complexity
Good wrapping does not hide complexity by pretending it does not exist. It keeps complexity in the right place.
The model engine is still complex. Loading failures, asset size, browser performance, cleanup leaks, and event order all need handling. The React component concentrates those problems so business pages do not repeat them.
This experience made me more careful about "integrating an SDK". Real integration is not just calling an API successfully. It is turning an external runtime into a component the team can use reliably.