Skip to content

Documentation Request: Include a complete, annotated implementation example #40

Open
@SigmaThetaTech

Description

@SigmaThetaTech

As someone who struggled to understand this library after reading it from top to bottom, word-for-word, I would've really appreciated a complete, back-to-front example of Roact-Rodux implementation. I wrote this script below to help anyone in the future that wants to poke and prod at a working example :) Please consider putting this in the documentation after peer reviewing my comments for accuracy!

--[[
This is a complete example of Roact-Rodux that will create a 
TextButton that will increment its text when its .Activated event is fired!

1) Put Roact, Rodux and RoactRodux in ReplicatedStorage
2) Paste this script in a LocalScript
]]

--Init
local PlayerGui = game.Players.LocalPlayer.PlayerGui
local RS = game:GetService("ReplicatedStorage")
local Roact = require(RS:WaitForChild("Roact"))
local Rodux = require(RS:WaitForChild("Rodux"))
local RoactRodux = require(RS:WaitForChild("RoactRodux"))

--Rodux creates our store:
local function reducer(state, action)
	state = state or {
		value = 0,
	}
	if action.type == "increment" then
		return {
			value = state.value+1
		}
	end
	return state
end

local store = Rodux.Store.new(reducer)

--Roact creates our component:
local function MyComponent(props)
	--Roact.createElement(ClassName, {Class Properties}, [{Children}])
	return Roact.createElement("ScreenGui", {}, {
		Roact.createElement("TextButton", {
			Text = props.value,
			AnchorPoint = Vector2.new(0.5, 0.5),
			Position = UDim2.new(0.5, 0, 0.5, 0),
			Size = UDim2.new(0, 500, 0, 200),
			ZIndex = 0,

			[Roact.Event.Activated] = props.onClick,
		})
	})
end

--`RoactRodux.connect([mapStateToProps, [mapDispatchToProps]])` returns a function that we can pass our plain Roact component `MyComponent` created above as an argument, returning a new RoactRodux-connected component as our new `MyComponent` variable
MyComponent = RoactRodux.connect(
	function(state, props) 	--`mapStateToProps` accepts our store's state and returns props
		return {
			value = state.value,
		}
	end,
	function(dispatch) 		--`mapDispatchToProps` accepts a dispatch function and returns props
		print("RoactRodux mapDispatchToProps has run.")
		return {
			onClick = function()
				dispatch({
					type = "increment",
				})
			end,
		}
	end
)(MyComponent) --Here we are passing in our plain Roact component as an argument to RoactRodux.connect(...)
--`MyComponent` should now return a RoactRodux-connected component, which will update and re-render any time the store is changed.

--Here we will wrap a RoactRodux StoreProvider at the top of our Roact component tree. This will make our store readable to the elements & components below it via 
local app = Roact.createElement(RoactRodux.StoreProvider, {
	store = store,
}, {
	Main = Roact.createElement(MyComponent), --Due to the limitations of Roact, we can only have ONE(1) child under a StoreProvider element, so we have to call MyComponent to get the rest of the children. The Store will be passed to MyComponent as arguments.
})

--Roact will now put our app on the screen
Roact.mount(app, PlayerGui, "My Test App")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions