### Roact Roact.Portal Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Example of using Roact.Portal to render children into a specified Roblox Instance container. ```lua function MyComponent:render() -- Roact does *not* create a new Roblox Instance. It renders the children into `instance`. -- `instance` is any valid Roblox Instance, regardless of its location in the DataModel. return Roact.createElement(Roact.Portal, { target = instance, }, self.props[Roact.Children]) end ``` -------------------------------- ### RoactCompat.Ref Example (Legacy Roact) Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Shows how to use Roact.Ref in a prop table for legacy Roact. ```lua Roact.createElement("TextLabel", { Text = "Hello", [Roact.Ref] = textLabelRef, }) ``` -------------------------------- ### RoactCompat.Children Example (Legacy Roact) Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Demonstrates forwarding children using Roact.Children in legacy Roact. ```lua -- forwards the children provided to this component Roact.createElement("Frame", nil, self.props[Roact.Children]) ``` -------------------------------- ### RoactCompat.Children Example (React Lua) Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Shows how to forward children in React Lua using the 'children' prop. ```lua -- forwards the children provided to this component Roact.createElement("Frame", nil, self.props.children) ``` -------------------------------- ### RoactCompat.Ref Example (React Lua) Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Shows the equivalent prop table in React Lua using the 'ref' prop. ```lua Roact.createElement("TextLabel", { Text = "Hello", ref = textLabelRef, }) ``` -------------------------------- ### React ReactDOM.createPortal Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Example of using ReactDOM.createPortal in React to render children into a specified DOM node. ```javascript render() { // React does *not* create a new div. It renders the children into `domNode`. // `domNode` is any valid DOM node, regardless of its location in the DOM. return ReactDOM.createPortal( this.props.children, domNode ); } ``` -------------------------------- ### Roact init example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Roact permits setState within the init function for consistency and correct interaction with derived state. ```lua function MyComponent:init(props) -- setState is preferred over `self.state =`, so that we can be consistent -- about our "don't assign to state" rule self:setState({counter = 0}) end ``` -------------------------------- ### useState and useEffect Hooks Example Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/adopt-new-features.md This example demonstrates the usage of `useState` for managing component state and `useEffect` for handling side effects in React Lua. Ensure you have the `React` package set up correctly. ```lua local React = require(Packages.React) function ClickerComponent(props) local count, setCount = React.useState(0) local function onClick() setCount(function(oldCount) return oldCount + 1 end) end React.useEffect(function() print(string.format("You've clicked %d times!", count)) end) return React.createElement("TextButton", { Text = tostring(count), [React.Event.Activated] = onClick, }) end ``` -------------------------------- ### Roact Ref Forwarding Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md In Roact, refs are primarily for Host components. This example shows ad-hoc forwarding by passing the `Roact.Ref` prop directly, which Roact treats as a regular prop for non-host components. ```lua local function FancyButton(props) return React.createElement("TextButton", { Text = props.text, -- Ad-hoc forwarding performed by passing along the `Roact.Ref` prop, which -- Roact does treats like any old prop. [Roact.Ref] = props[Roact.Ref], }, props.children) end -- You can now get a ref directly to the DOM button: local ref = React.createRef(); local element = React.createElement(FancyButton, {[Roact.Ref]=ref, text="Click me!"}) ``` -------------------------------- ### Roact createElement with children prop Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Example of how 'children' are passed as a prop in Roact using Roact.createElement and Roact.Children. ```lua local function Welcome(props) return Roact.createElement("Frame", nil, props[Roact.Children]); end ``` -------------------------------- ### Basic Ref Usage in Roact Source: https://github.com/jsdotlua/react-lua/blob/main/modules/react-roblox/README.md Illustrates a basic implementation of refs for UI elements in Roact. This example shows how refs are assigned to TextButtons. ```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 ``` -------------------------------- ### Roact NumberList Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Illustrates Roact's approach to stable keys using table keys and LayoutOrder for list items within a UIListLayout. ```lua function NumberList(props) local numbers = props.numbers; local listItems = { -- In Roblox, a UIListLayout establishes ordering and layout rules for -- its sibling elements ListLayout = Roact.createElement("UIListLayout", {SortOrder = Enum.SortOrder.LayoutOrder}) } for i, number in numbers do -- Here, the key in the list (`i`) is the key associated with the -- equivalently-numbered element. It can be any kind of value. listItems[i] = Roact.createElement("TextLabel", { Text = tostring(number), -- In Roblox, LayoutOrder must be specified, since an ordered list -- of elements has no guaranteed ordering in the dom LayoutOrder = i, }) end); return Roact.createElement("Frame", nil, listItems) end ``` -------------------------------- ### CreateElement with Refs and Instance Values Source: https://github.com/jsdotlua/react-lua/blob/main/docs/deviations.md This example demonstrates how to create TextButtons with refs and assign instance values to properties like NextSelectionRight and NextSelectionLeft. It highlights a potential issue where refs might be nil during rendering. ```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 ``` -------------------------------- ### React NumberList Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Demonstrates using the 'key' prop in React to provide stable identities for list items, improving performance during reordering. ```jsx function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // The number is stringified into a stable key associated with the // equivalently-numbered element
  • {number}
  • ); for (number in numbers) { listItems.append((
  • {number}
  • )); } return ( ); } ``` -------------------------------- ### Marking Deviations in Code Source: https://github.com/jsdotlua/react-lua/blob/main/docs/align-files-guide.md Example demonstrating how to mark unnecessary code with deviation comments (`-- ROBLOX deviation START:` and `-- ROBLOX deviation END`). This is used when automatic conversion requires manual adjustments. ```lua -- ROBLOX deviation START: -- Boolean.toJSBoolean(value) -- ROBLOX deviation END ``` -------------------------------- ### React constructor example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md In React, direct assignment to this.state is recommended within the constructor instead of using setState. ```javascript constructor(props) { super(props); // Don't call this.setState() here! this.state = { counter: 0 }; } ``` -------------------------------- ### React Fragment Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Illustrates how to use React fragments to return multiple sibling elements from a component's render method. ```javascript class Columns extends React.Component { render() { return ( <> Hello World ); } } ``` -------------------------------- ### Convert Specific Utility File Source: https://github.com/jsdotlua/react-lua/blob/main/docs/align-files-guide.md An example of converting a specific utility file (`utils.js`) to Lua. This command is a concrete instance of the file-by-file conversion process. ```shell dist/apps/convert-js-to-lua/index.js \ --input ../react/packages/react-devtools-shared/src/utils.js \ --output ../react-lua/modules/ \ --rootDir ../react/packages \ --plugin=knownImports --plugin=jestGlobals \ --babelTransformConfig babel-flow-transform-react.config.json \ --babelConfig babel-flow.config.json ``` -------------------------------- ### React 'ref' Prop Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Illustrates how to use React.createRef() to create and assign a ref to a component's DOM element. ```javascript class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return
    ; } } ``` -------------------------------- ### Roact State Initialization Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Illustrates Roact's behavior where uninitialized state defaults to an empty table. Accessing a non-existent key like 'count' will result in nil. ```lua local ShowCount = Roact.Component:extend("ShowCount") function ShowCount:init() -- self.state = {count=0} end function ShowCount:render() return Roact.createElement("TextLabel", { -- `self.state` is an empty table, and `self.state.count` is nil. -- Text will be left as its default value for a TextLabel Text = self.state.count, }) end ``` -------------------------------- ### React State Initialization Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Demonstrates how accessing uninitialized state in a React class component results in a runtime error. State must be initialized in the constructor. ```js class ShowCount extends React.Component { constructor(props) { super(props); // this.state = {count: 0}; } render() { return ( // Throws an error: // Uncaught TypeError: Cannot read property 'count' of null
    ${this.state.count}
    ); } } ``` -------------------------------- ### React useMemo Hook Example Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Demonstrates the `useMemo` hook for caching the result of an expensive computation. The computation is only re-executed if its dependencies change, improving performance by avoiding redundant calculations. ```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 createElement with children prop Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Example of how 'children' are passed as a prop in React using JSX. ```javascript function Welcome(props) { return

    {props.children}

    ; } ``` -------------------------------- ### Warning: Simultaneous Use of Key Methods Source: https://github.com/jsdotlua/react-lua/blob/main/docs/deviations.md This example illustrates a scenario where both table keys and the 'key' prop are used, which Roact flags as an error and issues a warning. It highlights the importance of choosing one method for key provision. ```lua return React.createElement("Frame", nil, { Label = React.createElement("TextLabel", { key = "label1", Text = "Hello", }) }) ``` -------------------------------- ### Roact Functional setState Example (Current) Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Shows the current functional setState usage in Roact, where 'self' is not directly in the function scope but can be closed over. ```lua self:setState(function(state, props) -- `self` is not in function scope (though it _can_ be closed over from -- outside of the function scope) return {counter = state.counter + props.step + self.CONSTANT} end) ``` -------------------------------- ### Roact Old Context: Provider Initialization Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Example of how a Roact component would provide context by mutating its `_context` field in `init`. This approach required manual subscription logic for consumers. ```lua function MyProvider:init() self._context.Theme = { --[[ some theme data ]] } end ``` -------------------------------- ### Roact Functional setState Example (Proposed) Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Illustrates the proposed Roact functional setState usage to align with React's behavior, explicitly accepting 'self' as the first argument. ```lua self:setState(function(self, state, props) return {counter = state.counter + props.step + self.CONSTANT} end) ``` -------------------------------- ### React useCallback Hook Example Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Shows how to use the `useCallback` hook to memoize a function definition, preventing unnecessary re-creation of the function on re-renders. This is useful for performance optimizations, especially when passing callbacks to child components. ```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 ``` -------------------------------- ### React useReducer Hook Example Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Demonstrates how to manage complex state using the `useReducer` hook with a custom reducer function. This is useful for state transitions that involve multiple sub-values or when the next state depends on the previous one. ```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 ``` -------------------------------- ### Roact Old Context: Consumer Render Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Example of a Roact consumer reading context from `_context`. This method discouraged overuse but lacked automatic updates and function component support. ```lua function MyConsumer:render() local theme = self._context.theme return props.render(theme) end ``` -------------------------------- ### Create and Join Bindings Source: https://github.com/jsdotlua/react-lua/blob/main/modules/react-roblox/README.md Demonstrates the basic usage of creating and joining bindings. These are Roact features tightly coupled with refs. ```lua ReactRoblox.createBinding(nil) ReactRoblox.joinBindings(binding1, binding2) ``` -------------------------------- ### Mounting, Updating, and Unmounting in React Lua Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/convert-legacy-conventions.md Shows the React Lua equivalent using `createRoot` for managing the lifecycle of UI components. ```lua local PlayerGui = game:GetService("Players").LocalPlayer.PlayerGui local React = require(Packages.React) local ReactRoblox = require(Packages.ReactRoblox) -- React Lua 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) ``` -------------------------------- ### Create a Legacy Root Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/adopt-new-features.md For compatibility with older patterns, `ReactRoblox.createLegacyRoot` is available, but it does not leverage Concurrent Mode optimizations. ```lua local root = ReactRoblox.createLegacyRoot(container) root:render(element) ``` -------------------------------- ### Mounting, Updating, and Unmounting in Legacy Roact Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/convert-legacy-conventions.md Demonstrates the legacy Roact functions for mounting, updating, and unmounting a Roact tree. ```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) ``` -------------------------------- ### React Functional setState Example Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Demonstrates how to use functional setState in React, where 'this' is implicitly accessible within the updater function. ```javascript this.setState((state, props) => { // `this` is implicitly accessible in this function body due to the calling // syntax in React internals return {counter: state.counter + props.step + this.CONSTANT}; }); ``` -------------------------------- ### Get Single Child with RoactCompat Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Mimics Roact.oneChild, providing functionality similar to React.Children.only. It can unwrap a table containing a single element. ```lua RoactCompat.oneChild( children: { [string | number]: ReactElement } | ReactElement | nil ): ReactElement ``` -------------------------------- ### React JS useEffect with Dependency Array Source: https://github.com/jsdotlua/react-lua/blob/main/docs/deviations.md Example of a React JS useEffect hook that re-runs only when the 'count' state changes. Dependency arrays should be specified inline. ```javascript useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // Only re-run the effect if count changes ``` -------------------------------- ### Ref Usage with Bindings for Ordering Source: https://github.com/jsdotlua/react-lua/blob/main/modules/react-roblox/README.md Shows how using refs as bindings can solve ordering issues when assigning properties like gamepad navigation. This ensures properties are correctly set even if elements render out of 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, }), }) -- ... ``` -------------------------------- ### Count Children with React.Children.count Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Use `React.Children.count` to get the total number of child elements within `props.children`. This is helpful for logging or conditional rendering 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 ``` -------------------------------- ### React Lua Compatible Context Implementation Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/minimum-requirements.md Demonstrates the modern approach using `createContext`, `Provider`, and `Consumer` for managing and accessing style context in React Lua. ```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 ``` -------------------------------- ### Create Fragment with RoactCompat Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Mimics Roact.createFragment using React.Fragment internally. Accepts a table of elements to create a fragment. ```lua RoactCompat.createFragment(elements: { [string | number]: ReactElement }): ReactElement ``` -------------------------------- ### Create a Root for Concurrent Mode Rendering Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/adopt-new-features.md Use `ReactRoblox.createRoot` to mount your Roact UI elements and enable Concurrent Mode for improved responsiveness. This is the recommended approach for new code. ```lua local root = ReactRoblox.createRoot(container) root:render(element) ``` -------------------------------- ### Transform Children with React.Children.map Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Use `React.Children.map` to transform each child element within `props.children`. It's useful for applying transformations or wrapping children with additional components, like adding `layoutOrder` in this example. ```lua local ListItem = require(script.Parent.ListItem) local function OrderedList(props) return React.createElement( "Frame", { Size = UDim2.fromScale(1, 1) }, React.Children.map(props.children, function(child, i) return React.createElement(ListItem, { layoutOrder = i }, child) end) ) end ``` -------------------------------- ### Create a React Component in Lua Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Define a React component using `React.Component:extend`. Implement an `init` method for initialization and use `self:setState` to manage state. The `render` method returns UI elements. ```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 ``` -------------------------------- ### Legacy Roact Component with Reserved 'key' Prop Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/minimum-requirements.md This snippet demonstrates a legacy Roact setup where the 'key' prop is used for component layout order, which will be interpreted as a stable key in React Lua. ```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 ``` -------------------------------- ### Build js-to-lua Converter Source: https://github.com/jsdotlua/react-lua/blob/main/docs/align-files-guide.md Build the js-to-lua conversion tool. Ensure you are in the js-to-lua directory before running this command. ```bash npx nx build convert-js-to-lua ``` -------------------------------- ### Legacy Roact Context Implementation Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/minimum-requirements.md Illustrates the deprecated usage of `self._context` for defining and reading style information in legacy 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 ``` -------------------------------- ### React useRef Hook Example Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Illustrates the `useRef` hook for creating a mutable reference container that persists across renders without causing re-renders. This is commonly used to access DOM elements or store arbitrary values. ```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 'ref' Prop Equivalent using Roact.Ref Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Shows the Roact equivalent of React's ref usage, employing Roact.createRef() and the special Roact.Ref Symbol as the prop key. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:init() self.myRef = Roact.createRef() end function MyComponent:render() { return React.createElement("Frame", { [Roact.Ref] = self.myRef, }) end ``` -------------------------------- ### Enable Legacy Roact Compatibility Warnings Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Set __COMPAT_WARNINGS__ to enable warnings for the Legacy Roact compatibility layer, aiding in forward compatibility. ```lua _G.__COMPAT_WARNINGS__ = true ``` -------------------------------- ### Unmount Roact Tree Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Compatibility method mimicking legacy Roact.unmount. ```lua RoactCompat.unmount(tree: RoactTreeHandle) ``` -------------------------------- ### Roact createFragment Usage Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Demonstrates the Roact equivalent of React fragments using Roact.createFragment to return multiple sibling elements. ```lua local Columns = React.Component:extend("Columns") function Columns:render() return React.createFragment({ React.createElement("TextLabel", {Text="Hello"}), React.createElement("TextLabel", {Text="World"}), }) end ``` -------------------------------- ### Configure Performance Profiling in Lua Source: https://github.com/jsdotlua/react-lua/blob/main/modules/react-reconciler/README.md Set up the global performance object with a mark function to enable profiling. This is required when using the Scheduling Profiler. ```lua _G.performance = { mark = function(str) debug.profileBegin(str) debug.profileEnd(str) } ``` -------------------------------- ### Legacy Roact Component with `Roact.Ref` Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/convert-legacy-conventions.md Illustrates how legacy Roact uses `[Roact.Ref]` to assign a ref to a component's element. ```lua local FocusButton = Roact.Component:extend("FocusButton") function FocusButton:init() self.ref = Roact.createRef() end function FocusButton:render() return Roact.createElement("Button", { Size = self.props.Size, [Roact.Ref] = self.ref }, self.props[Roact.Children]) end function FocusButton:didMount() GuiService.SelectedObject = self.ref.current end ``` -------------------------------- ### RoactCompat.mount Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Mounts a React element into a container, mimicking legacy Roact's mount behavior. ```APIDOC ## RoactCompat.mount ### Description Compatibility method mimicking [legacy `Roact.mount`](https://roblox.github.io/roact/api-reference/#roactmount). Mounts a React element into a specified container. Under the hood, this function creates a root, renders the element, and returns a handle for updates and unmounting. It handles legacy Roact compatibility by using a Portal to avoid tampering with existing children of the container. ### Method Signature ```lua RoactCompat.mount(element: ReactElement, container: Instance?, name: string?): RoactTree ``` ### Parameters * **element** (ReactElement) - Required - The React element to mount. * **container** (Instance?) - Optional - The parent Instance where the element will be mounted. If not provided, it defaults to the root of the game. * **name** (string?) - Optional - A name for the mount point, useful for debugging. ### Returns * **RoactTree** - An opaque handle to the root, used for subsequent updates and unmounting. ``` -------------------------------- ### RoactCompat.createContext Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Re-exports React.createContext from the React Lua package. ```APIDOC ## RoactCompat.createContext ### Description Re-exports [React.createContext](react.md#ReactcreateContext). ### Usage ```lua local createContext = RoactCompat.createContext ``` ``` -------------------------------- ### Create a Blocking Root Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/adopt-new-features.md If Concurrent Mode causes issues, `ReactRoblox.createBlockingRoot` can be used as an alternative, though it may impact overall application responsiveness. ```lua local root = ReactRoblox.createBlockingRoot(container) root:render(element) ``` -------------------------------- ### RoactCompat.createRef Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Re-exports React.createRef from the React Lua package. ```APIDOC ## RoactCompat.createRef ### Description Re-exports [React.createRef](react.md#ReactcreateRef). ### Usage ```lua local createRef = RoactCompat.createRef ``` ``` -------------------------------- ### Roact createFragment Compatibility Layer Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Provides a simple compatibility function for createFragment to align with React's fragment syntax, minimizing maintenance. ```lua function createFragment(elements) return React.createElement(React.Fragment, elements) end ``` -------------------------------- ### Enable DEV Mode with roblox-cli Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Use the --lua.globals=__DEV__=true argument with the 'run' command in roblox-cli to enable development mode. ```bash roblox-cli run --lua.globals=__DEV__=true ``` -------------------------------- ### Roact 17 Component with Prop Keys Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md An equivalent Roact 17 component explicitly assigning keys via the 'key' prop to its children. This demonstrates manual key management. ```lua function ChildrenArrayComponent(props) return Roact.createElement("Frame", nil, { -- These children receive keys 1, 2, and 3, respectively Roact.createElement(Foo, { key = 1 }), Roact.createElement(Foo, { key = 2 }), Roact.createElement(Bar, { key = 3 }), }) end ``` -------------------------------- ### RoactCompat.createElement Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Re-exports React.createElement from the React Lua package. ```APIDOC ## RoactCompat.createElement ### Description Re-exports [React.createElement](react.md#ReactcreateElement). ### Usage ```lua local createElement = RoactCompat.createElement ``` ``` -------------------------------- ### Mount a RoactCompat Component Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Mounts a React element into a specified container using RoactCompat. This function mimics the behavior of legacy Roact's mount function. It internally uses React.createRoot and React.createPortal to manage the component lifecycle within the container. The behavior can be influenced by global flags like `__ROACT_17_COMPAT_LEGACY_ROOT__` and `__ROACT_17_INLINE_ACT__`. ```lua RoactCompat.mount( element: ReactElement, container: Instance?, name: string? ): RoactTree ``` -------------------------------- ### Roact Re-mounting Case (Inefficient) Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Demonstrates an inefficient re-mounting scenario in Roact 17 where a single child element is rendered after multiple children, causing the child to remount instead of update. ```lua local root = Roact.createLegacyRoot(container) -- Initial Render root.render(Roact.createElement(Foo, nil, { Roact.createElement(Bar), Roact.createElement(Bar), Roact.createElement(FooBar), })) -- Re-Render -- Bar will be remounted here. Roact 17 cannot discern if this is -- the same Bar as above, so it remounts it. root.render(Roact.createElement(Foo, nil, Roact.createElement(Bar))) ``` -------------------------------- ### Connect to Roblox Instance Events with React.Event Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Use React.Event to connect to events on Roblox Instance objects. The event connection is automatically created on mount and disconnected on unmount. ```lua React.createElement("ImageButton", { [React.Event.MouseButton1Click] = function(rbx, x, y) print(rbx, "clicked at position", x, y) end, }) ``` -------------------------------- ### ReactRoblox.createPortal: Legacy Roact Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/convert-legacy-conventions.md Legacy Roact uses a special Roact.Portal component with a 'target' prop to define portals. ```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 ``` -------------------------------- ### Convert Entire Module Source: https://github.com/jsdotlua/react-lua/blob/main/docs/align-files-guide.md Use this command to convert all JavaScript files within a specified module to Lua. Ensure you are in the `js-to-lua` directory when executing. ```shell dist/apps/convert-js-to-lua/index.js \ --input ../react/packages/react-devtools-shared/src/**/*.js \ --output ../react-lua/modules/ \ --rootDir ../react/packages \ --plugin=knownImports --plugin=jestGlobals \ --babelTransformConfig babel-flow-transform-react.config.json \ --babelConfig babel-flow.config.json ``` -------------------------------- ### Update Roact Tree Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Mimics legacy Roact.update to update an existing Roact tree. The first argument must be a tree returned from RoactCompat.mount or RoactCompat.update. ```lua RoactCompat.update(tree: RoactTree, element: ReactElement): RoactTree ``` -------------------------------- ### Access DOM Instances with React.createRef Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Create a ref object to access underlying Roblox Instances. Use this for direct interaction with Instances, such as capturing focus on a TextBox. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:init() sself.inputRef = React.createRef() end function MyComponent:render() return React.createElement("TextBox", { ref = self.inputRef }) end function MyComponent:componentDidMount() sself.inputRef.current:CaptureFocus() end ``` -------------------------------- ### Roact Update Case (Efficient) Source: https://github.com/jsdotlua/react-lua/blob/main/DEVIATIONS.md Shows an efficient update scenario in Roact 17 by providing a key to a single child element, allowing Roact to match and update it instead of remounting. ```lua local root = Roact.createLegacyRoot(container) -- Initial Render -- Keys are not necessary here, they are applied by default -- as { 1 = Bar, 2 = Bar, 3 = FooBar } root.render(Roact.createElement(Foo, nil, { Roact.createElement(Bar), Roact.createElement(Bar), Roact.createElement(FooBar), })) -- Re-Render -- Bar will be updated here, as the key allows Roact 17 to match -- this Bar to the first Bar above. If we instead set key to 2, it -- would match the second Bar above root.render(Roact.createElement(Foo, nil, Roact.createElement(Bar, { key = 1 }) )) ``` -------------------------------- ### RoactCompat.unmount Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/roact-compat.md Compatibility method mimicking the legacy `Roact.unmount` function, used to unmount a Roact tree. ```APIDOC ## `RoactCompat.unmount` ### Description Compatibility method mimicking legacy `Roact.unmount`. ### Parameters * **tree** (RoactTreeHandle) - Required - The handle to the Roact tree to unmount. ``` -------------------------------- ### Using Table Keys for Stable Elements Source: https://github.com/jsdotlua/react-lua/blob/main/docs/deviations.md This snippet demonstrates how to provide stable keys using a Lua table where keys are explicitly defined. This method is useful when managing ordered lists of elements. ```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 ``` -------------------------------- ### Declare Legacy and React Lua Dependencies Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/upgrading-to-react-lua.md Specify both legacy Roact and React Lua (as a dev dependency) in your rotriever.toml manifest. This allows for coexistence during the migration phase. ```toml [dependencies] Roact = "github.com/roblox/roact@1.4" [dev_dependencies] RoactCompat = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Add React and ReactRoblox for New Features Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/upgrading-to-react-lua.md Include React and ReactRoblox dependencies in rotriever.toml to access new React Lua features like hooks and suspense. RoactCompat can be used alongside these new packages. ```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" ``` ``` -------------------------------- ### React.Fragment: Legacy Roact Source: https://github.com/jsdotlua/react-lua/blob/main/docs/migrating-from-legacy/convert-legacy-conventions.md Legacy Roact uses Roact.createFragment to create fragments, which are distinct rendered objects. ```lua local function LabeledButton(props) return Roact.createFragment({ Button = Roact.createElement("ImageButton", { Image = props.buttonIcon, }), Label = Roact.createElement("TextLabel", { Text = props.labelText, }), }) end ``` -------------------------------- ### React.createElement Source: https://github.com/jsdotlua/react-lua/blob/main/docs/api-reference/react.md Creates a React element. This is used directly in React Lua as JSX is not supported by current tooling. ```APIDOC ## `React.createElement` ### Description Creates a React element. This function is essential for defining UI structures in React Lua, especially since JSX is not directly supported. ### Syntax ```lua React.createElement(type, [props], [...children]) ``` ### Parameters - **type** (string | Component) - The type of the element to create (e.g., 'Frame', 'TextLabel'). - **[props]** (table, optional) - An object containing properties for the element. - **[...children]** (ReactElement, optional) - Child elements to be rendered within this element. ### Usage Example ```lua local element = React.createElement( "Frame", { Size = UDim2.fromScale(1, 1) }, React.createElement("TextLabel", { Text = "Child1" }) React.createElement("TextLabel", { Text = "Child2" }) ) ``` ```