### Basic Hello World Example Source: https://github.com/haedrix/react-luau/blob/main/README.md This example demonstrates how to render a simple 'Hello, [name]!' message using React Luau. It sets up a basic component and renders it to the player's GUI. ```luau local React = require(Packages.React) local ReactRoblox = require(Packages.ReactRoblox) local e = React.createElement local function HelloMessage(props: { name: string, }) return e("TextLabel", { AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), AutomaticSize = Enum.AutomaticSize.XY, Text = `Hello, {props.name}!`, }) end local function App() return e("ScreenGui", {}, { MyMessage = e(HelloMessage, { name = "Taylor", }), }) end local root = ReactRoblox.createRoot(Instance.new("Folder")) root:render(ReactRoblox.createPortal(e(App), Players.LocalPlayer.PlayerGui)) ``` -------------------------------- ### Example: Convert Specific File to Lua Source: https://github.com/haedrix/react-luau/blob/main/docs/align-files-guide.md An example demonstrating the file-by-file conversion command, targeting a specific utility file within the react-devtools-shared module. ```shell dist/apps/convert-js-to-lua/index.js \ --input ../react/packages/react-devtools-shared/src/utils.js \ --output ../roact-alignment/modules/ \ --rootDir ../react/packages \ --plugin=knownImports --plugin=jestGlobals \ --babelTransformConfig babel-flow-transform-react.config.json \ --babelConfig babel-flow.config.json ``` -------------------------------- ### Legacy Roact Context API Example Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/minimum-requirements.md Demonstrates the legacy method of reading and defining style from context in Roact. ```lua local AppStyle = require(script.Parent.AppStyle) local Label = Roact.Component:extend("Label") function Label:init() -- reading style from context self.style = self._context.style end function Label:render() return Roact.createElement("TextLabel", { BackgroundColor3 = self.style.LabelColor, Text = props.text, }) end local App = Roact.Component:extend("App") function App:init() -- defining style in context self._context.style = AppStyle end function App:render() return Roact.createElement("Frame", { Size = UDim2.fromScale(1, 1) }, { Start = Roact.createElement(Button, { text = "Hello World", }) }) end ``` -------------------------------- ### Roact Class Component Constructor (init) Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This example shows the 'init' lifecycle method in Roact, which serves as the constructor for class components. It runs immediately after an instance is created and can be used for initial state setup. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:init(props) sself.state = { initialized = true } end function MyComponent:render() return React.createElement("TextLabel", {Text = self.props.text}) end ``` -------------------------------- ### Legacy Roact Portal Example Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md This snippet demonstrates how to create a modal using `Roact.Portal` in legacy Roact. The portal's target is set to `PlayerGui`. ```lua local PlayerGui = game:GetService("Players").LocalPlayer.PlayerGui local function Modal(props) return Roact.createElement(Roact.Portal, { target = PlayerGui, }, { Modal = Roact.createElement("ScreenGui", {}, { Label = Roact.createElement("TextButton", { Text = "Click me to close!", [Roact.Event.Activated] = props.onClose, }) }) }) end ``` -------------------------------- ### Roact 17 Portal Example Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md This snippet shows the equivalent modal creation in Roact 17 using `ReactRoblox.createPortal`. The target `PlayerGui` is now passed as the second argument. ```lua local PlayerGui = game:GetService("Players").LocalPlayer.PlayerGui local function Modal(props) return ReactRoblox.createPortal({ Modal = Roact.createElement("ScreenGui", {}, { Label = Roact.createElement("TextButton", { Text = "Click me to close!", [Roact.Event.Activated] = props.onClose, }) }) }, PlayerGui) end ``` -------------------------------- ### React useMemo Hook Example Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Shows how `useMemo` can be used to cache the result of an expensive computation. It accepts a function that computes the value and a dependency array. ```lua local function filterByCategory(todos, category) -- ... return filteredTodos end local function FilteredTodoList(props) local filteredTodos = React.useMemo(function() return filterByCategory(props.todos, props.selectedCategory) end, { props.todos, props.selectedCategory }) return React.createElement(TodoList, { items = filteredTodos, }) end ``` -------------------------------- ### React useReducer Hook Example Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Demonstrates how to use the `useReducer` hook for managing complex state logic in a component. It requires a reducer function and an initial state. ```lua local function reducer(state, action) if action.type == "add" then return { value = state.value + action.value, ops = state.ops + 1, } elseif action.type == "multiply" then return { value = state.value * action.value, ops = state.ops + 1, } end end local function Calculator(props) local state, dispatch = React.useReducer(reducer, { value = 1, ops = 0 }) return React.createElement(React.Fragment, nil, React.createElement("TextLabel", { Text = string.format("value: %d - ops: %d", state.value, state.ops) }) React.createElement("TextButton", { Text = "Add 4", [React.Event.Activated] = function() dispatch({ type = "add", value = 4 }) end }) React.createElement("TextButton", { Text = "Multiply by 3", [React.Event.Activated] = function() dispatch({ type = "multiply", value = 3 }) end }) ) end ``` ```js const [state, dispatch] = useReducer(reducer, initialState); ``` ```lua local state, dispatch = useReducer(reducer, initialState) ``` -------------------------------- ### Roact Duplicate Key Warning Example Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This example demonstrates a scenario where Roact would issue a warning due to providing keys using both table keys and the 'key' prop simultaneously. Roact falls back to the explicitly provided key in such cases. ```lua return React.createElement("Frame", nil, { Label = React.createElement("TextLabel", { key = "label1", Text = "Hello", }) }) ``` -------------------------------- ### React Component with State and Event Handling Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Example of creating a React component in Luau using `Component:extend`. It demonstrates initializing state with `setState` and handling user interaction via `React.Event.Activated`. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:init() sself:setState({ expanded = true }) end function MyComponent:render() return React.createElement("TextButton", { Text = if expanded then self.props.text else "Click to Expand", Size = if expanded then UDim2.new(1, 0, 0, 200) else UDim2.new(1, 0, 0, 30), [React.Event.Activated] = function() self:setState(function(expanded) return { expanded = not expanded } end) end }) end ``` -------------------------------- ### Roact 17 Compatible OptionButton and ButtonGroup Components Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/minimum-requirements.md This example demonstrates the fix for the reserved prop conflict by renaming the 'key' prop to 'order'. This ensures compatibility with Roact 17+. ```lua local function OptionButton(props) return Roact.createElement("TextButton", { LayoutOrder = props.order, Text = props.text, [Roact.Event.Activated] = props.onClick, }) end local function ButtonGroup(props) return Roact.createFragment({ CancelButton = Roact.createElement(OptionButton, { order = 1, text = "Cancel", onClick = props.cancelCallback, }) ConfirmButton = Roact.createElement(OptionButton, { order = 2, text = "Confirm", onClick = props.confirmCallback, }) }) end ``` -------------------------------- ### Roact Component with Instance References Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This example demonstrates a basic Roact component that creates Instance references for two TextButtons. It highlights the potential issue with assigning refs directly to properties like NextSelectionRight/Left when the order of rendering is not guaranteed. ```lua local PopupButtons = Roact.Component:extend("PopupButtons") function PopupButtons:init() sself.confirmRef = Roact.createRef() sself.cancelRef = Roact.createRef() end function PopupButtons:render() --[[ "Some Description" [ Confirm ] [ Cancel ] ]] return Roact.createElement("Frame", nil { ConfirmButton = Roact.createElement("TextButton", { [Roact.Ref] = self.confirmRef, Text = "Confirm", NextSelectionRight = self.cancelRef.value, }), CancelButton = Roact.createElement("TextButton", { [Roact.Ref] = self.cancelRef, Text = "Confirm", NextSelectionLeft = self.confirmRef.value, }), }) end ``` -------------------------------- ### Legacy OptionButton and ButtonGroup Components Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/minimum-requirements.md This example shows a legacy implementation where 'key' is used as a prop for LayoutOrder, which conflicts with Roact's reserved 'key' prop in version 17+. ```lua local function OptionButton(props) return Roact.createElement("TextButton", { LayoutOrder = props.key, Text = props.text, [Roact.Event.Activated] = props.onClick, }) end local function ButtonGroup(props) return Roact.createFragment({ CancelButton = Roact.createElement(OptionButton, { key = 1, text = "Cancel", onClick = props.cancelCallback, }) ConfirmButton = Roact.createElement(OptionButton, { key = 2, text = "Confirm", onClick = props.confirmCallback, }) }) end ``` -------------------------------- ### Creating a Binding with React.createBinding Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Example of using React.createBinding to create a binding object, useful for managing state within class components. The binding can be mapped to update UI elements. ```lua local DisplaysSize = React.Component:extend("DisplaysSize") function DisplaysSize:init() self.absSize, self.setAbsSize = React.createBinding(Vector2.new(0, 0)) end function DisplaysSize:render() return React.createElement(React.Fragment, nil, React.createElement("ImageLabel", { Image = self.props.image, [React.Change.AbsoluteSize] = function(rbx) self.setAbsSize(rbx.AbsoluteSize) end, }), React.createElement("TextLabel", { Text = self.absSize:map(function(value) return "X = " .. tostring(value.X) .. "; Y = " .. tostring(value.Y) end) } ) end ``` -------------------------------- ### React useCallback Hook Example Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Illustrates using `useCallback` to memoize a function, preventing unnecessary re-creations on re-renders. It takes a callback function and a dependency array. ```lua local ItemTile = require(...) local equipItem = require(...) local function EquippableItemTile(props) local onClick = React.useCallback(function() equipItem(props.itemId) end, { props.itemId }) return React.createElement(ItemTile, { text = props.itemName, onTileClicked = onClick, }) end ``` -------------------------------- ### Combine Bindings with React.joinBindings Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md This example demonstrates how to use React.joinBindings to combine two size bindings (aSize and bSize) into a single Size property for a Frame. The combined size is calculated by summing the individual sizes. This is useful for creating UI elements whose dimensions depend on multiple sub-elements. ```lua local function Flex() local aSize, setASize = React.useBinding(Vector2.new()) local bSize, setBSize = React.useBinding(Vector2.new()) return React.createElement( "Frame", { Size = React.joinBindings({aSize, bSize}):map(function(sizes) local sum = Vector2.new() for _, size in sizes do sum += size end return UDim2.new(0, sum.X, 0, sum.Y) end), }, React.createElement("Frame", { Size = UDim2.new(1, 0, 0, 30), [React.Change.AbsoluteSize] = function(instance) setASize(instance.Size) end, }), React.createElement("Frame", { Size = UDim2.new(1, 0, 0, 30), Position = aSize:map(function(size) return UDim2.new(0, 0, 0, size.Y) end), [React.Change.AbsoluteSize] = function(instance) setBSize(instance.Size) end, }) ) end ``` -------------------------------- ### TooltipButton Component Example Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/adopt-new-features.md This Lua component demonstrates a button that shows a tooltip when clicked and hides it after a delay. It uses `React.useState` to manage the tooltip's visibility. ```lua local function TooltipButton(props) local showTooltip, setShowTooltip = React.useState(false) return React.createElement("Frame", { key = "TooltipButton", Size = UDim2.fromScale(1, 1), }, { Button = React.createElement("TextButton", { Text = "Show tooltip", Active = props.enabled, [React.Event.Activated] = function() setShowTooltip(true) task.delay(props.tooltipFadeDelay, function() setShowTooltip(false) end) end, }) Tooltip = if showTooltip then React.createElement("TextLabel", { Text = "Tooltip text!", }) else nil end) end ``` -------------------------------- ### Connecting to Roblox Events with React.Event Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Example of using React.Event to connect to Roblox Instance events like MouseButton1Click. The event connection is managed automatically on mount and unmount. ```lua Roact.createElement("ImageButton", { [React.Event.MouseButton1Click] = function(rbx, x, y) print(rbx, "clicked at position", x, y) end, }) ``` -------------------------------- ### Legacy ReactDOM.render Example Source: https://github.com/haedrix/react-luau/blob/main/modules/react-roblox/README.md This snippet shows the traditional way to render a React component into the DOM using ReactDOM.render. It is being phased out in favor of new root APIs in React 18. ```javascript ReactDOM.render(

Hello, world!

, document.getElementById('root') ); ``` -------------------------------- ### React useRef Hook Example Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Demonstrates the `useRef` hook for creating a mutable reference that persists across renders without causing re-renders. Useful for accessing DOM elements or storing non-rendering state. ```lua local function TextBoxWithButton(props) local textBoxRef = React.useRef(nil) return React.createElement(React.Fragment, nil, React.createElement("TextBox", { ref = textBoxRef }), React.createElement("TextButton", { Text = "->", [React.Event.Activated] = function() textBoxRef.current:CaptureFocus() end }), ) end ``` -------------------------------- ### Roact setState with Function Updater in Constructor Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This example shows using a function as the updater argument for setState within a Roact class component's 'init' method. This allows for state updates based on previous state values. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:init(props) sself.setState(function(previousState) return { counter = (previousState.counter or 0) + 1 } end) end function MyComponent:render() return React.createElement("TextLabel", {Text = "Counter: " .. tostring(self.state.counter)}) end ``` -------------------------------- ### Legacy Roact Mounting, Updating, and Unmounting Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Demonstrates the traditional method of managing Roact UI lifecycle using `Roact.mount`, `Roact.update`, and `Roact.unmount`. ```lua local PlayerGui = game:GetService("Players").LocalPlayer.PlayerGui local Roact = require(Packages.Roact) local roactTree = Roact.mount(Roact.createElement("TextLabel", { Text = "Hello world!", }, PlayerGui) task.wait(3) roactTree = Roact.update(roactTree, Roact.createElement("TextLabel", { Text = "Hello Roblox!", }) task.wait(3) Roact.unmount(roactTree) ``` -------------------------------- ### Roact 17 Mounting, Updating, and Unmounting with createRoot Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Shows the Roact 17 approach using `ReactRoblox.createRoot` for managing UI lifecycle, including rendering and unmounting. ```lua local PlayerGui = game:GetService("Players").LocalPlayer.PlayerGui local React = require(Packages.React) local ReactRoblox = require(Packages.ReactRoblox) -- Roact 17 roots will take full ownership of the instance provided to them, -- so we should not create a root using PlayerGui directly local container = Instance.new("Folder") container.Parent = PlayerGui local root = ReactRoblox.createRoot(container) root:render(Roact.createElement("TextLabel", { Text = "Hello world!", }) task.wait(3) root:render(Roact.createElement("TextLabel", { Text = "Hello Roblox!", }) task.wait(3) root:render(nil) ``` -------------------------------- ### Legacy Ref Forwarding with Roact.Ref Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/minimum-requirements.md Illustrates the legacy method of implicit ref forwarding using the `[Roact.Ref]` prop in Roact. ```lua local function FancyButton(props) return Roact.createElement("TextBox", { PlaceholderText = "Enter your text here", PlaceholderColor3 = Color3.new(0.4, 0.4, 0.4), [Roact.Change.Text] = props.onTextChange, -- Implicitly forwarding a ref via the `Roact.Ref` prop [Roact.Ref] = props[Roact.Ref], }) end ``` -------------------------------- ### Require and Connect to DevTools Source: https://github.com/haedrix/react-luau/blob/main/modules/react-devtools-core/README.md Demonstrates how to require the React DevTools Core package and set up a connection to DevTools with a custom configuration. Ensure this is called before importing any React packages. ```luau local ReactDevtoolsCore = require(Packages.ReactDevtoolsCore) local connectToDevtools = ReactDevtoolsCore.connectToDevtools connectToDevTools(config) ``` -------------------------------- ### Roact 17+ Context API with createContext Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/minimum-requirements.md Shows how to use Roact 17's createContext API for managing and consuming context, replacing the legacy context approach. ```lua local AppStyle = require(script.Parent.AppStyle) local StyleContext = Roact.createContext(nil) local Label = Roact.Component:extend("Label") function Label:render() return Roact.createElement(StyleContext.Consumer, { render = function(style) return Roact.createElement("TextLabel", { BackgroundColor3 = style.LabelColor, Text = props.text, end }) end }) local App = Roact.Component:extend("App") function App:render() return Roact.createElement(StyleContext.Provider, { value = AppStyle, }, { App = Roact.createElement("Frame", { Size = UDim2.fromScale(1, 1) }, { Start = Roact.createElement(Button, { text = "Hello World", }) }) }) end ``` -------------------------------- ### Basic Ref Usage for UI Elements Source: https://github.com/haedrix/react-luau/blob/main/modules/react-roblox/README.md Demonstrates the basic usage of Roact refs for TextButton elements, including setting text and initial neighbor selection. ```lua local PopupButtons = Roact.Component:extend("PopupButtons") function PopupButtons:init() sself.confirmRef = Roact.createRef() sself.cancelRef = Roact.createRef() end function PopupButtons:render() --[[ "Some Description" [ Confirm ] [ Cancel ] ]] return Roact.createElement("Frame", nil { ConfirmButton = Roact.createElement("TextButton", { [Roact.Ref] = self.confirmRef, Text = "Confirm", NextSelectionRight = self.cancelRef.value, }), CancelButton = Roact.createElement("TextButton", { [Roact.Ref] = self.cancelRef, Text = "Confirm", NextSelectionLeft = self.confirmRef.value, }), }) end ``` -------------------------------- ### Count React children Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Use React.Children.count to get the total number of children provided to a component. This is useful for logging or conditional logic based on the number of children. ```lua local function List(props) print(string.format("Render list with %d children", React.Children.count(props.children))) return React.createElement( "Frame", { Size = UDim2.fromScale(1, 1) }, props.children, ) end ``` -------------------------------- ### Ref Usage with Bindings for UI Navigation Source: https://github.com/haedrix/react-luau/blob/main/modules/react-roblox/README.md Illustrates how using refs as bindings can solve issues with assigning neighbor selections in Roact, ensuring correct property assignment regardless of render order. ```lua -- ... return Roact.createElement("Frame", nil { ConfirmButton = Roact.createElement("TextButton", { [Roact.Ref] = self.confirmRef, Text = "Confirm", -- pass the ref itself, which is a binding NextSelectionRight = self.cancelRef, }), CancelButton = Roact.createElement("TextButton", { [Roact.Ref] = self.cancelRef, Text = "Confirm", -- pass the ref itself, which is a binding NextSelectionLeft = self.confirmRef, }), }) -- ... ``` -------------------------------- ### useEffect Dependency Array in React JS Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md In React JS, useEffect accepts a dependency array to determine re-invocation. This example shows a typical usage where the effect re-runs only if 'count' changes. ```javascript useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // Only re-run the effect if count changes ``` -------------------------------- ### Create and Join Bindings Source: https://github.com/haedrix/react-luau/blob/main/modules/react-roblox/README.md Provides functions for creating and joining bindings, a Roact feature tightly coupled with refs. ```lua ReactRoblox.createBinding(nil) ReactRoblox.joinBindings(binding1, binding2) ``` -------------------------------- ### Getting the Single Child with RoactCompat Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md RoactCompat.oneChild is a compatibility method for legacy Roact.oneChild, designed to extract a single child element from various inputs, including a table containing one element. ```Lua RoactCompat.oneChild( children: { [string | number]: ReactElement } | ReactElement | nil ): ReactElement ``` -------------------------------- ### RoactCompat.Ref for Legacy Roact Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Shows how to use Roact.Ref with legacy Roact prop tables. This field is equivalent to the string 'ref' in RoactCompat. ```lua Roact.createElement("TextLabel", { Text = "Hello", [Roact.Ref] = textLabelRef, }) ``` -------------------------------- ### Mapping Binding Values for Display Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md The map method transforms a binding's value into a new binding, suitable for display or use with Roblox Instance properties. This example formats a count into a user-friendly string. ```lua local function UpdateOnClick() local count, setCount = React.useBinding(0) return React.createElement("TextButton", { Text = count:map(function(value) return string.format("Clicked %d times", value) end), [React.Event.Activated] = function() setCount(count:getValue() + 1) end, }) end ``` -------------------------------- ### Mounting an Element with RoactCompat Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Use RoactCompat.mount to render a ReactElement into a container, mimicking legacy Roact's mounting behavior. It returns a handle for subsequent updates or unmounting. ```Lua RoactCompat.mount( element: ReactElement, container: Instance?, name: string? ): RoactTree ``` -------------------------------- ### Using RoactCompat Portal Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md The RoactCompat.Portal component is a compatibility layer that mimics legacy Roact.Portal, using React.createPortal internally to render children into a different DOM subtree. ```Lua RoactCompat.Portal ``` -------------------------------- ### Roact useEffect with Potential Dependency Array Warning Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This Roact example illustrates a scenario where a dependency array's length might change between renders, potentially causing warnings in React JS. Roact 17+ introduces deviations to handle this. ```lua local root = ReactRoblox.createRoot(someContainer) local function Component(props: { A: number, B: number? }) React.useEffect(function() -- Trigger some effect end, { props.A, props.B }) return nil end -- does not warn: root:render(React.createElement(Component, { A = 1, B = 2 })) -- subsequent render warns about different length arrays: root:render(React.createElement(Component, { A = 1 })) ``` -------------------------------- ### React.memo for Performance Optimization Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Demonstrates using `React.memo` to create a memoized component for performance optimization. This is useful when a component renders the same output given the same props. ```lua local MyComponent = React.memo(function MyComponent(props) --[[ render using props ]] end) ``` -------------------------------- ### RoactCompat.mount Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Mounts a React element into a container, mimicking legacy Roact's mount behavior. It creates a root, renders the element, and returns a handle for updates and unmounting. It handles legacy root creation and uses Portals to avoid tampering with existing container children. ```APIDOC ## RoactCompat.mount ### Description Compatibility method mimicking legacy `Roact.mount`. Creates a root, renders the provided element into the container, and returns an opaque handle to the root. ### Method `RoactCompat.mount(element: ReactElement, container: Instance?, name: string?): RoactTree` ### Parameters * **element** (ReactElement) - The React element to mount. * **container** (Instance?, optional) - The DOM Instance to mount the element into. * **name** (string?, optional) - An optional name for the tree. ### Returns * **RoactTree** - An opaque handle to the root, usable with `RoactCompat.update` and `RoactCompat.unmount`. ``` -------------------------------- ### Creating a Fragment with RoactCompat Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md RoactCompat.createFragment mimics legacy Roact's createFragment, utilizing React.Fragment internally to group multiple elements. ```Lua RoactCompat.createFragment(elements: { [string | number]: ReactElement }): ReactElement ``` -------------------------------- ### Roact 17+ Explicit Ref Forwarding with forwardRef Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/minimum-requirements.md Demonstrates explicit ref forwarding in Roact 17+ using the `Roact.forwardRef` API, which is the recommended approach. ```lua local FancyButton = Roact.forwardRef(function(props, ref) return Roact.createElement("TextBox", { PlaceholderText = "Enter your text here", PlaceholderColor3 = Color3.new(0.4, 0.4, 0.4), [Roact.Change.Text] = props.onTextChange, -- Explicitly forwarding a ref passed in via `forwardRef` [Roact.Ref] = ref, end) end) ``` -------------------------------- ### Applying CollectionService Tags with React.Tag Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Shows how to use React.Tag to apply CollectionService tags to a host component. Multiple tags can be applied using a space-delimited string. ```lua local button = Roact.createElement("TextButton", { [React.Tag] = "confirm-button" Text = "Confirm", -- ... }) ``` ```lua [React.Tag] = "some-tag some-other-tag" ``` -------------------------------- ### RoactCompat.Children for Legacy Roact Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Demonstrates forwarding children using Roact.Children with legacy Roact. This field is equivalent to the string 'children' in RoactCompat. ```lua -- forwards the children provided to this component Roact.createElement("Frame", nil, self.props[Roact.Children]) ``` -------------------------------- ### Migrate Legacy Roact Context.Consumer Usage Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Adapt legacy Roact `Context.Consumer` usage, which uses a `render` prop, to the Roact 17 pattern that expects children as a function. ```lua local ThemeContext = Roact.createContext(nil) -- ... local function Button(props) return Roact.createElement(ThemeContext.Consumer, { render = function(theme) return Roact.createElement("TextButton", { BackgroundColor3 = theme.ButtonColor, Text = props.text, [Roact.Event.Activated] = props.onActivated, }) end }) end ``` ```lua local ThemeContext = Roact.createContext(nil) -- ... local function Button(props) return Roact.createElement(ThemeContext.Consumer, nil, function(theme) return Roact.createElement("TextButton", { BackgroundColor3 = theme.ButtonColor, Text = props.text, [Roact.Event.Activated] = props.onActivated, }) end end ``` -------------------------------- ### Add Roact 17 Dependencies to New Projects Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/upgrading-to-roact-17.md Add these lines to your `rotriever.toml` to include Roact 17 packages for a new project. Ensure you are using Rotriever version 0.5.4 or newer. ```toml [dependencies] React = "github.com/roblox/roact-alignment@17.0.1" ReactRoblox = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Convert Entire Module to Lua Source: https://github.com/haedrix/react-luau/blob/main/docs/align-files-guide.md Use this command to convert all JavaScript files within a specified directory to Lua. This is suitable for smaller modules or when you want to convert a large set of files at once. ```shell dist/apps/convert-js-to-lua/index.js \ --input ../react/packages/react-devtools-shared/src/**/*.js \ --output ../roact-alignment/modules/ \ --rootDir ../react/packages \ --plugin=knownImports --plugin=jestGlobals \ --babelTransformConfig babel-flow-transform-react.config.json \ --babelConfig babel-flow.config.json ``` -------------------------------- ### RoactCompat.Portal Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md A compatibility component that mimics `Roact.Portal`. It internally uses the `React.createPortal` function. ```APIDOC ## RoactCompat.Portal ### Description Compatibility component mimicking `Roact.Portal`. Uses the `React.createPortal` function under the hood. ### Component `RoactCompat.Portal` ### Props * **children** (ReactElement) - The children to render within the portal. * **target** (Instance) - The target Instance where the children will be rendered. ``` -------------------------------- ### Using ReactRoblox.createRoot for Concurrent Mode Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/adopt-new-features.md In new code, always use ReactRoblox.createRoot to enable Concurrent Mode and improve application responsiveness. This is the recommended entry point for rendering Roact UI elements in Roact 17. ```lua local ReactRoblox = require(ReplicatedStorage.ReactRoblox) local root = ReactRoblox.createRoot(workspace.App) root:render(React.createElement('ScreenGui')) ``` -------------------------------- ### Testing Tooltip Behavior with `act` Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/adopt-new-features.md This Lua test suite demonstrates how to use the `act` function to test component behavior, including rendering, state changes, and asynchronous operations like delayed callbacks. It ensures that all scheduled work is flushed before assertions. ```lua local React = require(Packages.React) local ReactRoblox = require(Packages.ReactRoblox) local container, root beforeEach(function() container = Instance.new("ScreenGui") container.Parent = Players.LocalPlayer.PlayerGui root = ReactRoblox.createRoot(container) end) afterEach(function() container:Destroy() end) it("shows a tooltip on click and hides it after a delay", function() -- Use `act` for the initial render ReactRoblox.act(function() -- Render the button in a disabled state root:render(React.createElement(TooltipButton, { enabled = false, tooltipFadeDelay = 1, })) end) expect(container.TooltipButton.Tooltip).toBeNil() expect(container.TooltipButton.Button.Active).toBe(false) -- Use `act` to re-render the tree ReactRoblox.act(function() -- Rerender in the enabled state root:render(React.createElement(TooltipButton, { enabled = true, tooltipFadeDelay = 1, })) end) expect(container.TooltipButton.Tooltip).toBeNil() expect(container.TooltipButton.Button.Active).toBe(true) -- Use `act` to trigger virtual input local element = Rhodium.Element.new(container.TooltipButton.Button) ReactRoblox.act(function() -- Click the button to trigger the tooltip element:click() Rhodium.VirtualInput.waitForInputEventsProcessed() end) expect(container.TooltipButton.Tooltip).never.toBeNil() expect(container.TooltipButton.Tooltip.Text).toEqual("Tooltip text!") -- Use `act` to resume queued renders after a delayed callback fires ReactRoblox.act(function() task.wait(1) end) expect(container.TooltipButton.Tooltip).toBeNil() end) ``` -------------------------------- ### Roact List with Table Keys Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This snippet demonstrates how to render a list of items using table keys in Roact. It iterates over a table of numbers and assigns a string representation of the index as the key for each TextLabel element. ```lua -- Returns a fragment of items in an ordered list function NumberList(props) local numbers = props.numbers for i, number in numbers do local key = tostring(i) listItems[key] = React.createElement("TextLabel", { Text = key, LayoutOrder = i, }) end); return listItems end ``` -------------------------------- ### Roact setState in Constructor (Recommended) Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This snippet demonstrates the recommended way to use setState within the 'init' method (constructor) of a Roact class component. It shows how to update state using setState, avoiding direct assignment to self.state. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:init(props) sself.setState({ initialized = true }) end function MyComponent:render() return React.createElement("TextLabel", {Text = self.props.text}) end ``` -------------------------------- ### Setting Global Configuration with RoactCompat Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md RoactCompat.setGlobalConfig is a compatibility method that mimics legacy Roact.setGlobalConfig. However, it is a no-op in Roact 17 and does not apply any global configuration. ```Lua RoactCompat.setGlobalConfig(configValues: { [string]: boolean }) ``` -------------------------------- ### RoactCompat.Ref for Roact 17 Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Shows the equivalent prop table for Roact 17, which uses 'ref' as a reserved prop name. This is compatible with RoactCompat. ```lua Roact.createElement("TextLabel", { Text = "Hello", ref = textLabelRef, }) ``` -------------------------------- ### React.createElement Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Creates a React element. This is used directly in Luau as JSX is not supported. It takes the element type, props, and children as arguments. ```APIDOC ## React.createElement ### Description Creates a React element. This is used directly in Luau as JSX is not supported. It takes the element type, props, and children as arguments. ### Signature ```lua React.createElement(type, [props], [...children]) ``` ### Example ```lua local element = React.createElement( "Frame", { Size = UDim2.fromScale(1, 1) }, React.createElement("TextLabel", { Text = "Child1" }) React.createElement("TextLabel", { Text = "Child2" }) ) ``` ``` -------------------------------- ### Configure Roact Dependencies in rotriever.toml Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/upgrading-to-roact-17.md Declare dependencies on both legacy Roact and Roact 17 (RoactCompat) in your rotriever.toml manifest file. RoactCompat is listed as a dev dependency. ```toml [dependencies] Roact = "github.com/roblox/roact@1.4" [dev_dependencies] RoactCompat = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Roact List with 'key' Prop Source: https://github.com/haedrix/react-luau/blob/main/docs/deviations.md This snippet shows how to render a list of items using the special 'key' prop in Roact. It iterates over a table of numbers and assigns a string representation of the index to the 'key' prop of each TextLabel element. ```lua -- Returns a fragment of items in an ordered list function NumberList(props) local numbers = props.numbers for i, number in numbers do local key = tostring(i) local element = React.createElement("TextLabel", { key = key, Text = key, LayoutOrder = i, }) table.insert(listItems, element) end); return listItems end ``` -------------------------------- ### Updating an Element with RoactCompat Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Use RoactCompat.update to re-render an existing Roact tree with a new element. The tree handle must be from a prior RoactCompat.mount or RoactCompat.update call. ```Lua RoactCompat.update(tree: RoactTree, element: ReactElement): RoactTree ``` -------------------------------- ### Connecting to Property Changes with React.Change Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Demonstrates using React.Change to connect to property change signals on Roblox Instances, such as CanvasPosition for ScrollingFrame. The connection is managed automatically. ```lua Roact.createElement("ScrollingFrame", { [React.Change.CanvasPosition] = function(rbx) print("ScrollingFrame scrolled to", rbx.CanvasPosition) end, }) ``` -------------------------------- ### Access Instances with React.createRef Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Create a ref object using React.createRef to access underlying Roblox Instances. This is useful for direct interaction with Instances. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:init() self.inputRef = React.createRef() end function MyComponent:render() return React.createElement("TextBox", { ref = self.inputRef }) end function MyComponent:componentDidMount() sself.inputRef.current:CaptureFocus() end ``` -------------------------------- ### RoactCompat.Children for Roact 17 Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Shows the equivalent prop table for Roact 17, which uses 'children' as a reserved prop name. This is compatible with RoactCompat. ```lua -- forwards the children provided to this component Roact.createElement("Frame", nil, self.props.children) ``` -------------------------------- ### Convert Single File to Lua Source: https://github.com/haedrix/react-luau/blob/main/docs/align-files-guide.md This command converts a specific JavaScript file to Lua. It's recommended for modules with many unconverted files, allowing for more granular control over the conversion process. ```shell dist/apps/convert-js-to-lua/index.js \ --input ../react/packages/react-devtools-shared/src/ \ --output ../roact-alignment/modules/ \ --rootDir ../react/packages \ --plugin=knownImports --plugin=jestGlobals \ --babelTransformConfig babel-flow-transform-react.config.json \ --babelConfig babel-flow.config.json ``` -------------------------------- ### Using useBinding Hook in a Function Component Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/adopt-new-features.md Demonstrates how to use the useBinding hook to manage state in a function component. Updates to the binding directly update subscribed values without re-rendering the component. ```lua local React = require(Packages.React) function ClickerComponent(props) local count, setCount = React.useBinding(0) local function onClick() -- This will only update subscribed host properties, specifically the -- Text field of the button that's rendered below setCount(count:getValue() + 1) end React.useEffect(function() print(string.format("You've clicked %d times!", count)) end) return React.createElement("TextButton", { Text = count:map(tostring), [React.Event.Activated] = onClick, }) end ``` -------------------------------- ### Replace Legacy Roact Dependency Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/upgrading-to-roact-17.md Modify your `rotriever.toml` to use the RoactCompat package for backward compatibility with legacy Roact APIs. This allows upgrading without immediate code changes if minimum requirements are met. ```toml [dependencies] Roact = { target = "github.com/roblox/roact-alignment", version = "17.0.1", package = "RoactCompat" } ``` -------------------------------- ### Add Roact 17 and ReactRoblox Dependencies Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/upgrading-to-roact-17.md To access new Roact 17 features like hooks and suspense, add `React` and `ReactRoblox` dependencies alongside `RoactCompat` in your `rotriever.toml`. ```toml [dependencies] Roact = { target = "github.com/roblox/roact-alignment", version = "17.0.1", package = "RoactCompat" } React = "github.com/roblox/roact-alignment@17.0.1" ReactRoblox = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Create a Context Object with React.createContext Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md Use React.createContext to create a Context object. Context provides a way to pass data through the component tree without prop drilling. ```lua local MyContext = React.createContext(defaultValue) ``` -------------------------------- ### Convert Legacy Roact Fragment Creation Source: https://github.com/haedrix/react-luau/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Replace `Roact.createFragment` with `React.createElement(React.Fragment, ...)` to use fragments in Roact 17, aligning with React JS. ```lua local function LabeledButton(props) return Roact.createFragment({ Button = Roact.createElement("ImageButton", { Image = props.buttonIcon, }), Label = Roact.createElement("TextLabel", { Text = props.labelText, }), }) end ``` ```lua local function LabeledButton(props) return React.createElement(React.Fragment, nil, { Button = React.createElement("ImageButton", { Image = props.buttonIcon, }), Label = React.createElement("TextLabel", { Text = props.labelText, }), }) end ``` -------------------------------- ### Creating Updatable Bindings with useBinding Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/react.md useBinding creates a Binding object and an updater function, similar to useState. Bindings are isolated containers that automatically update when their value changes. ```lua local function DisplaysSize(props) local absSize, setAbsSize = React.useBinding(Vector2.new(0, 0)) return React.createElement(React.Fragment, nil, React.createElement("ImageLabel", { Image = props.image, [React.Change.AbsoluteSize] = function(rbx) setAbsSize(rbx.AbsoluteSize) end, }), React.createElement("TextLabel", { Text = absSize:map(function(value) return "X = " .. tostring(value.X) .. "; Y = " .. tostring(value.Y) end) } ) end ``` -------------------------------- ### RoactCompat.setGlobalConfig Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Mimics legacy Roact's `setGlobalConfig`. However, this function is a no-op in Roact 17 and does not apply any global configuration. ```APIDOC ## RoactCompat.setGlobalConfig ### Description Compatibility method mimicking `Roact.setGlobalConfig`. **This does not apply to Roact 17, so calling this function is a no-op.** ### Method `RoactCompat.setGlobalConfig(configValues: { [string]: boolean })` ### Parameters * **configValues** ({ [string]: boolean }) - An object containing configuration values. This parameter is ignored. ``` -------------------------------- ### RoactCompat.update Source: https://github.com/haedrix/react-luau/blob/main/docs/api-reference/roact-compat.md Updates a previously mounted React tree with a new element, mimicking legacy Roact's update behavior. This function requires a handle obtained from `RoactCompat.mount` or a previous `RoactCompat.update` call. ```APIDOC ## RoactCompat.update ### Description Compatibility method mimicking legacy `Roact.update`. Updates a mounted tree with a new element. ### Method `RoactCompat.update(tree: RoactTree, element: ReactElement): RoactTree` ### Parameters * **tree** (RoactTree) - The handle returned from a prior call to `RoactCompat.mount` or `RoactCompat.update`. * **element** (ReactElement) - The new React element to render. ### Returns * **RoactTree** - An opaque handle to the root, usable with `RoactCompat.update` and `RoactCompat.unmount`. ```