Roblox / roact

A view management library for Roblox Lua similar to React
https://roblox.github.io/roact
Apache License 2.0
563 stars 143 forks source link

Allow Roact children to come from different Roact sources #252

Closed Kampfkarren closed 4 years ago

Kampfkarren commented 4 years ago

I am mixing a game written in Lua with code from roblox-ts. I am writing a component with roblox-ts, which uses its own copy of Roact. However, when I try to use the compiled component in a Lua script, I get the following error: Component returned invalid children.

Minimum repro:

local Roact1 = require(Roact1)
local Roact2 = require(Roact2) -- A different copy of Roact

local function App()
    return Roact1.createElement("Frame", {}, {
        Roact2.createElement("Frame"),
    })
end

...and mount.

LPGhatguy commented 4 years ago

This is something that the Roact team has talked about before internally. We laid out a couple principles that still hold:

Supporting objects from different Roact versions is not feasible. The internals of objects like Component and Element can differ between versions while still having compatible user-facing APIs. We don't really want to deal with a compatibility matrix of mixing Roact versions.

We believe the onus is on package managers and other tools to ensure there's only one copy of Roact. This is something that Roblox-TS should address, and something that package managers should handle ideally. We have releases that follow SemVer to make this as easy as we can, and we'll be releasing our own package manager soon™.

Roact is not the only library that falls over when mixed with other versions of itself. This happens with other Roblox libraries, React, and lots of JavaScript libraries due to the nature of operators like instanceof.

I don't think we'll be pursuing this right now, but if something changes we can reevaluate this decision in the future!

tiffany352 commented 4 years ago

It's probably not applicable to your use case but it's also possible to write an adapter that lets you nest a subtree using a different Roact. You write a Roact1 component that in its didMount will mount the Roact2 tree etc.