react-lua icon indicating copy to clipboard operation
react-lua copied to clipboard

`React.Attributes` should be implemented

Open Nidoxs opened this issue 1 year ago • 1 comments

This will allow attributes to be applied to instances. While I've not had a need for this myself, there's others who have and I think it'd be an appropriate addition to the prop marker symbols.

Example:

return e("TextLabel", {
    [React.Attributes] = {
        Test = 100,
        MyBool = false
    }
})

Draft PR for full changes proposed: #39

Nidoxs avatar Oct 11 '24 09:10 Nidoxs

A new PropMarker symbol would need to be created for attributes:

local Symbol = require("../Symbol.roblox.luau")

local Attributes = Symbol.named("RobloxAttributes")

return Attributes

I've prototyped this on my end and I propose the following function to be added to modules\react-roblox\src\client\roblox\RobloxComponentProps.luau

-- these types could be put somewhere else in a more accessible file
type AcceptableAttributeType =
	string
	| boolean
	| number
	| UDim
	| UDim2
	| BrickColor
	| Color3
	| Vector2
	| Vector3
	| EnumItem
type AttributesDictionary = { [string]: AcceptableAttributeType }

local function applyAttributes(
	hostInstance: Instance,
	oldAttributes: AttributesDictionary,
	newAttributes: AttributesDictionary
)
	if __DEV__ then
		if newAttributes ~= nil then
			if typeof(newAttributes) ~= "table" then
				console.error(
					"Type provided for ReactRoblox.Attributes is invalid - attributes should be "
						.. "specified as a dictionary, where the key-value pairs represent the "
						.. "attribute names and their respective values. Instead received:\n%s",
					inspect(newAttributes)
				)
			end
			return
		end
	end

	if oldAttributes then
		for attributeName in oldAttributes do
			if newAttributes == nil or newAttributes[attributeName] == nil then
				hostInstance:SetAttribute(attributeName, nil)
			end
		end
	end

	if newAttributes then
		for attributeName, value in newAttributes do
			hostInstance:SetAttribute(attributeName, value)
		end
	end
end

I would have done this work myself, but I'm unsure on the testing workflow here and I don't want to contribute work that I cannot write tests for.

It also seems that the original team working on react-lua anticipated testing some behaviours outside of the Roblox DataModel / environment, as I have come across a module that mocks the behaviour of CollectionService tags when it comes to adding, updating and removing them. See https://github.com/jsdotlua/react-lua/blob/main/modules/react-test-renderer/src/roblox/RobloxComponentProps.luau

The point here is that there should probably be a similar thing for mocking attributes being set, updated and removed. I am unsure if this is needed though.

Nidoxs avatar Oct 11 '24 10:10 Nidoxs