### Build js-to-lua Conversion Tool Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Instructions to build the `convert-js-to-lua` tool using `npx nx build` from within the `js-to-lua` directory, as part of the tool installation process. ```Shell npx nx build convert-js-to-lua ``` -------------------------------- ### Convert JavaScript to Lua using `js-to-lua` Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Commands for converting JavaScript code to Lua using the `js-to-lua` tool. This process involves specifying input/output directories, a root directory, and applying various plugins and Babel configurations for transformation. Examples include converting entire modules or single files. ```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 ``` ```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 ``` ```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 ``` -------------------------------- ### Insert Roblox Deviation Start Marker (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Inserts a '-- ROBLOX deviation START:' comment, used to mark the beginning of a code deviation block. This snippet helps avoid typos and ensures consistent formatting for deviation markers. ```Lua -- ROBLOX deviation START: ${0:description} ``` ```JSON { "Deviation block - start": { "prefix": "deviation-start", "body": "-- ROBLOX deviation START: ${0:description}", "description": "Roblox deviation start marker" } } ``` -------------------------------- ### Add New Code Block with Deviation Marker (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Wraps the currently selected block of code with deviation START/END comments and allows for the insertion of additional code. This is intended for new code blocks not present in the original conversion, following the convention '-- ROBLOX deviation START: add ' to easily distinguish added sections. ```Lua -- ROBLOX deviation START: ${0:add some code} ${TM_SELECTED_TEXT} ${1} -- ROBLOX deviation END ``` ```JSON { "Deviation block - add": { "prefix": "deviation-block-add", "body": [ "-- ROBLOX deviation START: ${0:add some code}", "${TM_SELECTED_TEXT}", "${1}", "-- ROBLOX deviation END" ], "description": "Roblox deviation end marker" } } ``` -------------------------------- ### Install Foreman using Rust and Cargo Source: https://github.com/roblox/react-lua/blob/main/README.md Installs Rust and Cargo using the official 'rustup' script, adds Cargo's bin directory to the PATH, and then uses Cargo to install the 'foreman' package. Foreman is an un-package manager for retrieving code from GitHub. ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh export PATH=$PATH:$HOME/.cargo/bin cargo install foreman ``` -------------------------------- ### Authenticate Foreman and Install Lua Dependencies Source: https://github.com/roblox/react-lua/blob/main/README.md Authenticates Foreman with a GitHub API token, allowing it to access private tools. It then installs the packages listed in 'foreman.toml' and adds Foreman's bin directory to the system's PATH for easy access to installed tools like Rotriever. ```bash foreman github-auth foreman install export PATH=~/.foreman/bin/:$PATH ``` -------------------------------- ### React and Roact Portal Component Usage Examples Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md Examples demonstrating how to use portals in React (via `ReactDOM.createPortal`) and Roact (via `Roact.Portal` component) to render children into an external container. ```js 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 ); } ``` ```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 ``` -------------------------------- ### Install Roblox Aged CLI Globally Source: https://github.com/roblox/react-lua/blob/main/README.md Installs the @roblox/rbx-aged-cli package globally using npm. This tool is used for downloading Roblox-specific command-line utilities. ```bash npm install --global @roblox/rbx-aged-cli ``` -------------------------------- ### Install Yarn for Upstream React Test Development Source: https://github.com/roblox/react-lua/blob/main/README.md These commands install Yarn globally and then use it to download the necessary development dependencies for running and debugging upstream React tests. This is a prerequisite step before attempting to run any ReactJS tests. ```Shell npm install --global yarn yarn ``` -------------------------------- ### Install Lua Package Dependencies using Rotriever Source: https://github.com/roblox/react-lua/blob/main/README.md Uses Rotriever, a Lua package manager installed by Foreman, to install the project's Lua package dependencies. These dependencies are specified in the 'rotriever.toml' file. ```bash rotrieve install ``` -------------------------------- ### Lua Performance Global Setup for Profiling Source: https://github.com/roblox/react-lua/blob/main/modules/react-reconciler/README.md Demonstrates how to configure the `_G.performance` global in Lua to enable profiling. It uses `debug.profileBegin` and `debug.profileEnd` to mark profiling sections. ```Lua _G.performance = { mark = function(str) debug.profileBegin(str) debug.profileEnd(str) } ``` -------------------------------- ### Wrap Selected Code with Deviation Block (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Comments out the currently selected code, wraps it with '-- ROBLOX deviation START/END' comments, and inserts a duplicated version of the same code for modification. This is useful for tracking changes made to original code. ```Lua -- ROBLOX deviation START: ${0:changed because} -- ${TM_SELECTED_TEXT/\n/\n-- /g} $TM_SELECTED_TEXT -- ROBLOX deviation END ``` ```JSON { "Deviation block": { "prefix": "deviation-block", "body": [ "-- ROBLOX deviation START: ${0:changed because}", "-- ${TM_SELECTED_TEXT/\\n/\\n-- /g}", "$TM_SELECTED_TEXT", "-- ROBLOX deviation END" ], "description": "Roblox deviation end marker" } } ``` -------------------------------- ### React-Lua Hooks Example: useState and useEffect Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/adopt-new-features.md Illustrates the use of `useState` and `useEffect` hooks in a React-Lua functional component. The `ClickerComponent` tracks click count using `useState` and prints the updated count to the console using `useEffect` on each render. ```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 ``` -------------------------------- ### Legacy ReactDOM.render API Usage Example Source: https://github.com/roblox/react-lua/blob/main/modules/react-roblox/README.md This JavaScript code snippet illustrates the traditional `ReactDOM.render` function, which was commonly used to mount a React component into a specified DOM element. This API is considered legacy and is being superseded by the new 'root' APIs in React 18. ```JavaScript ReactDOM.render(

Hello, world!

, document.getElementById('root') ); ``` -------------------------------- ### Excluded Forked Configuration Files Source: https://github.com/roblox/react-lua/blob/main/modules/shared/README.md Files related to React's feature flag system that are excluded due to lack of equivalent bundler functionality and environment setup in the Roblox Lua port. ```plaintext forks/ReactFeatureFlags.native-fb.js forks/ReactFeatureFlags.native-oss.js forks/ReactFeatureFlags.readonly.js forks/ReactFeatureFlags.test-renderer.js forks/ReactFeatureFlags.test-renderer.native.js forks/ReactFeatureFlags.test-renderer.www.js forks/ReactFeatureFlags.testing.js forks/ReactFeatureFlags.testing.www.js forks/ReactFeatureFlags.www-dynamic.js forks/ReactFeatureFlags.www.js forks/Scheduler.umd.js forks/SchedulerTracing.umd.js forks/consoleWithStackDev.www.js forks/invokeGuardedCallbackImpl.www.js forks/object-assign.inline-umd.js forks/object-assign.umd.js ``` -------------------------------- ### Roact Old Context Provider Example Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md Illustrates the deprecated method of providing context in Roact by directly mutating the `_context` field within a component's `init` function. This approach did not trigger updates in consumers. ```lua function MyProvider:init() self._context.Theme = { --[[ some theme data ]] } end ``` -------------------------------- ### Roact Old Context Consumer Example Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md Shows how a Roact component would access context values from the `_context` field. This method was not intended for widespread use and required manual subscription logic for updates. ```lua function MyConsumer:render() local theme = self._context.theme return props.render(theme) end ``` -------------------------------- ### React and Roact setState Functional Update Examples Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md Illustrates the differences and proposed alignment for functional `setState` updates between React (JavaScript) and Roact (Lua), specifically regarding the accessibility of `this`/`self` within the updater function. ```js 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}; }); ``` ```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) ``` ```lua self:setState(function(self, state, props) return {counter = state.counter + props.step + self.CONSTANT} end) ``` -------------------------------- ### JavaScript: React forwardRef API Example Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md This JavaScript example demonstrates how to use React's `forwardRef` API to pass a ref from a parent component down to a child's DOM element. The `FancyButton` component receives a ref and attaches it to its underlying ` )); // You can now get a ref directly to the DOM button: const ref = React.createRef(); Click me!; ``` -------------------------------- ### Configure rotriever.toml for Roact 17 Compatibility Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/upgrading-to-roact-17.md This TOML configuration declares a dependency on legacy Roact (1.4) and a development dependency on Roact 17 (17.0.1) using `rotriever.toml`. This setup allows projects to conditionally adopt Roact 17 in tests or development environments. ```toml [dependencies] Roact = "github.com/roblox/roact@1.4" [dev_dependencies] RoactCompat = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Wrap Current Line with Deviation Markers (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Similar to `deviation-block`, but applies the deviation marking to the current line instead of a selected block. It comments out the current line and duplicates it within deviation START/END comments. ```Lua -- ROBLOX deviation START: ${0:changed because} -- $TM_CURRENT_LINE $TM_CURRENT_LINE -- ROBLOX deviation END ``` ```JSON { "Deviation line": { "prefix": "deviation-line", "body": ["-- ROBLOX deviation START: ${0:changed because}", "-- $TM_CURRENT_LINE", "$TM_CURRENT_LINE", "-- ROBLOX deviation END"], "description": "Roblox deviation end marker" } } ``` -------------------------------- ### Roact Class Components: Example Usage of React.Component:extend Source: https://github.com/roblox/react-lua/blob/main/docs/deviations.md Demonstrates how to create a class component in Roact using `React.Component:extend`. It shows the definition of `render` and `componentDidMount` lifecycle methods, illustrating how component properties (`self.props.text`) are accessed and used. ```lua local MyComponent = React.Component:extend("MyComponent") function MyComponent:render() return React.createElement("TextLabel", {Text = self.props.text}) end function MyComponent:componentDidMount() print("rendered with text " .. self.props.text) end ``` -------------------------------- ### Roact Component with Refs and NextSelection (Initial Problematic Implementation) Source: https://github.com/roblox/react-lua/blob/main/modules/react-roblox/README.md An example of a Roact component using `Roact.createRef()` for `TextButton` instances and attempting to set `NextSelectionRight`/`NextSelectionLeft` properties using `ref.value`. This implementation highlights a rendering order problem where `ref.value` might be `nil` when accessed, leading to incorrect gamepad neighbor assignments. ```Lua local PopupButtons = Roact.Component:extend("PopupButtons") function PopupButtons:init() self.confirmRef = Roact.createRef() self.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 ``` -------------------------------- ### Clone React Element in Lua Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react.md Clones an existing React element, using its provided configuration (props, ref, and key) as a starting point. This function allows for creating new elements based on existing ones while potentially overriding or adding new properties. ```lua local onlyChild = React.Children.only(props.children) local cloned = React.cloneElement(onlyChild, { Text = "Cloned" }) ``` -------------------------------- ### Wrap Code for Type Import Deviation (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Wraps a block of code with deviation comments, comments out the original block, and inserts a duplicate where 'local' declarations are changed to 'type'. This snippet is useful when `js-to-lua` incorrectly imports locals instead of types. ```Lua -- ROBLOX deviation START: ${0:import as type instead of local} -- ${TM_SELECTED_TEXT/\n/\n-- /g} ${TM_SELECTED_TEXT/^local /type /gm} -- ROBLOX deviation END ``` ```JSON { "Deviation block - type": { "prefix": "deviation-block-type", "body": [ "-- ROBLOX deviation START: ${0:import as type instead of local}", "-- ${TM_SELECTED_TEXT/\\n/\\n-- /g}", "${TM_SELECTED_TEXT/^local /type /gm}", "-- ROBLOX deviation END" ], "description": "Roblox deviation end marker" } } ``` -------------------------------- ### Migrating from Reserved Props in Roact Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/minimum-requirements.md Roact 17+ reserves certain prop keywords like 'ref', 'key', and 'children'. If components use these as custom prop names, their values will be consumed by Roact or overridden. This example demonstrates how to migrate a component that uses 'key' as a custom prop by renaming it to 'order' to ensure compatibility with Roact 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 ``` ```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 ``` -------------------------------- ### Combine Multiple React Bindings with React.joinBindings in Lua Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react.md This example demonstrates how to use `React.joinBindings` to create a single binding that aggregates values from multiple input bindings. It shows a `Flex` component where the `Frame` size is dynamically calculated based on the sizes of two child frames, `aSize` and `bSize`, which are themselves updated via `React.Change.AbsoluteSize` events. This allows the parent frame's size to react to changes in its children's sizes. ```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 ``` -------------------------------- ### Lua: Roact Ref Forwarding via Roact.Ref Prop Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md This Lua example illustrates how ref forwarding was traditionally handled in Roact. It shows a `FancyButton` function component that manually passes the `[Roact.Ref]` prop to an underlying host component (`TextButton`). This method relies on Roact treating `[Roact.Ref]` 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 Component with Refs as Bindings (Corrected Implementation) Source: https://github.com/roblox/react-lua/blob/main/modules/react-roblox/README.md A corrected example demonstrating how to pass the ref itself (which acts as a binding) directly to properties like `NextSelectionRight`/`NextSelectionLeft`. This leverages the underlying binding logic to ensure properties are updated correctly even if refs are not yet assigned during initial render, solving the rendering order problem for gamepad navigation. ```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, }), }) -- ... ``` -------------------------------- ### Roact 17: ReactRoblox.createRoot API for Concurrent Mode Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/adopt-new-features.md Explains the `ReactRoblox.createRoot` API, the recommended entry point for new Roact applications to enable Concurrent Mode. It contrasts with legacy `Roact.mount` and discusses `createBlockingRoot` and `createLegacyRoot` as alternatives for specific use cases, emphasizing `createRoot`'s role in improving application responsiveness. ```APIDOC ReactRoblox.createRoot(container: Instance, options?: object): Root Purpose: Primary entry-point for rendering a Roact component tree in Concurrent Mode. Parameters: container: The Roact instance or equivalent where the UI elements will be mounted. options: Optional configuration object. Returns: A Root object with a `render` method. Usage Notes: - Recommended for new code to enable Concurrent Mode and improve responsiveness. - Replaces legacy `Roact.mount` and `ReactDOM.render` (from React JS 17 and older). - Alternatives: `ReactRoblox.createBlockingRoot` and `ReactRoblox.createLegacyRoot` are available for synchronous rendering, but at a cost to overall app responsiveness. ``` -------------------------------- ### Migrating Roact UI Lifecycle Management Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Demonstrates the transition from legacy Roact's `mount`, `update`, and `unmount` functions to Roact 17's root-based API (`createRoot`, `render`, `unmount`). It illustrates how to manage the lifecycle of an entire Roact tree using the new `ReactRoblox.createRoot` approach. ```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) ``` ```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) ``` -------------------------------- ### Download and Configure Roblox CLI Source: https://github.com/roblox/react-lua/blob/main/README.md Creates a 'bin' directory in the home folder, downloads the 'roblox-cli' tool into it using 'rbx-aged-cli', and adds the directory to the system's PATH. This allows 'roblox-cli' to be executed from any location. ```bash mkdir ~/bin rbx-aged-cli download roblox-cli --dst ~/bin export PATH=$PATH:~/bin roblox-cli --help ``` -------------------------------- ### Roact 17 Core API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Overview of the primary APIs exposed by the `React` and `ReactRoblox` packages in Roact 17, detailing their functionalities and replacements for legacy Roact APIs. This includes core legacy APIs, React-JS-aligned updates, and brand new APIs. ```APIDOC React: - createElement: Core legacy Roact API (unchanged) - createContext: Core legacy Roact API (unchanged) - Component: Core legacy Roact API (unchanged) - Change: Core legacy Roact API (unchanged) - Event: Core legacy Roact API (unchanged) - Fragment: Replaces createFragment - Children.only: Replaces oneChild - useState: New API - useRef: New API - memo: New API - cloneElement: New API ReactRoblox: - createRoot: Replaces mount/update/unmount APIs - createPortal: Replaces Roact.Portal component ``` -------------------------------- ### RoactCompat.createBinding API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/roact-compat.md Provides compatibility by re-exporting ReactRoblox.createBinding. ```APIDOC RoactCompat.createBinding: Re-exports ReactRoblox.createBinding ``` -------------------------------- ### ReactRoblox.createBlockingRoot API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react-roblox.md Documents the `createBlockingRoot` method, a transitional API for Concurrent Mode. It represents a step between synchronous rendering and full concurrent rendering, mirroring `ReactDOM.createBlockingRoot`. ```APIDOC ReactRoblox.createBlockingRoot Adopted as part of the Concurrent Mode API. "Blocking" roots represent a transitional step between synchronous rendering and full concurrent rendering. Refer to `ReactDOM.createBlockingRoot` documentation. ``` -------------------------------- ### Mark Current Line as Skipped Deviation (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Similar to `deviation-block-skipped`, but applies to the current line. It comments out the current line and wraps it with deviation START/END comments, indicating it should be skipped. ```Lua -- ROBLOX deviation START: ${0:changed because} -- $TM_CURRENT_LINE -- ROBLOX deviation END ``` ```JSON { "Deviation line - skipped": { "prefix": "deviation-line-skipped", "body": ["-- ROBLOX deviation START: ${0:changed because}", "-- $TM_CURRENT_LINE", "-- ROBLOX deviation END"], "description": "Roblox deviation end marker" } } ``` -------------------------------- ### RoactCompat.mount Function Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/roact-compat.md Compatibility method mimicking legacy `Roact.mount`. This function creates a root using `React.createRoot` (or `React.createLegacyRoot` if `_G.__ROACT_17_COMPAT_LEGACY_ROOT__` is enabled), renders the provided element, and returns an opaque handle. It uses a Portal to mimic legacy behavior of not tampering with existing children and can wrap the render call in `ReactRoblox.act` for synchronous test resolution. ```APIDOC RoactCompat.mount( element: ReactElement, container: Instance?, name: string? ): RoactTree ``` -------------------------------- ### Customize Ref Handle with React.useImperativeHandle in Lua Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react.md The `useImperativeHandle` hook allows customizing the ref handle exposed by a component, providing a narrower or more convenient interface than a direct instance reference. This example demonstrates how to expose a `scrollToTop` method for a `ScrollingFrame`. ```lua local ControllableScrollingFrame = React.forwardRef(function(props, ref) local innerRef = React.useRef(nil) React.useImperativeHandle(ref, function() return { scrollToTop = function() innerRef.current.CanvasPosition = Vector2.new(0, 0) end } end, {}) return React.createElement("ScrollingFrame", { ref = innerRef -- ... }) end) -- Another component will be able to access this interface via a ref: local function TodoListApp(props) local scrollingFrameRef = React.useRef(nil) return React.createElement(ControllableScrollingFrame, { ref = scrollingFrameRef }, React.createElement(TodoList, { items = props.todoItems, }), React.createElement("TextButton", { Text = "Back to top", [React.Event.Activated] = function() scrollingFrameRef.current.scrollToTop() end }) ) end ``` -------------------------------- ### ReactRoblox.createRoot API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react-roblox.md Documents the `createRoot` method, part of the Concurrent Mode API, which is the recommended way to create a root for managing React component trees in Roblox, similar to `ReactDOM.createRoot`. ```APIDOC ReactRoblox.createRoot Adopted as part of the Concurrent Mode API. Refer to `ReactDOM.createRoot` documentation. ``` -------------------------------- ### RoactCompat.joinBindings API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/roact-compat.md Provides compatibility by re-exporting ReactRoblox.joinBindings. ```APIDOC RoactCompat.joinBindings: Re-exports ReactRoblox.joinBindings ``` -------------------------------- ### ReactRoblox.createPortal API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react-roblox.md Documents the `createPortal` method, which allows rendering children into a different part of the DOM tree, consistent with `ReactDOM.createPortal`. ```APIDOC ReactRoblox.createPortal Refer to `ReactDOM.createPortal` documentation. ``` -------------------------------- ### RoactCompat.None API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/roact-compat.md Provides compatibility by re-exporting React.None. ```APIDOC RoactCompat.None: Re-exports React.None ``` -------------------------------- ### Creating a Modal with Legacy Roact.Portal Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Demonstrates how to create a modal component using `Roact.Portal` in Legacy Roact. The `target` property is passed as a table entry to `Roact.createElement`, allowing the modal to render into a specific `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 ``` -------------------------------- ### Authenticate with GitHub Package Registry using npm Source: https://github.com/roblox/react-lua/blob/main/README.md This command logs into the GitHub Package Registry for the @roblox scope. The password required is a GitHub Personal Access Token with 'repo' and 'read:packages' scopes enabled, and SSO enabled. ```bash npm login --registry=https://npm.pkg.github.com/ --scope=@roblox ``` -------------------------------- ### Insert Roblox Deviation End Marker (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Inserts a '-- ROBLOX deviation END' comment, used to mark the conclusion of a code deviation block. This snippet helps ensure consistent formatting for deviation markers. ```Lua -- ROBLOX deviation END ``` ```JSON { "Deviation block - end": { "prefix": "deviation-end", "body": "-- ROBLOX deviation END", "description": "Roblox deviation end marker" } } ``` -------------------------------- ### Force Roact Compat Mount to Create Legacy Root Source: https://github.com/roblox/react-lua/blob/main/docs/configuration.md Ensures that the `RoactCompat.mount` function creates a Legacy Root instead of the default Concurrent Root. This is useful for preserving old behavior in specific testing scenarios. ```APIDOC Global: __ROACT_17_COMPAT_LEGACY_ROOT__ Type: boolean Description: When true, forces the RoactCompat.mount compatibility function to create a Legacy Root instead of the default Concurrent Root. Usage: Useful for preserving old behavior in specific testing scenarios. Alternative: For explicit legacy root in production, use the createLegacyRoot API. ``` -------------------------------- ### Roact.Portal and ReactDOM.createPortal API Reference Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md API documentation comparing the structure and parameters of Roact's `Roact.Portal` component and React's `ReactDOM.createPortal` function, highlighting their functional equivalence despite different API shapes. ```APIDOC Roact.Portal: Type: Special Component Props: target: Roblox Instance (container for portal contents) [Roact.Children]: Standard children prop ReactDOM.createPortal: Type: Function Signature: ReactDOM.createPortal(children, container) Parameters: children: React nodes to render container: Valid DOM node (container for portal contents) ``` -------------------------------- ### ReactRoblox.createLegacyRoot API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react-roblox.md Documents the `createLegacyRoot` method, which provides behavior equivalent to pre-Concurrent Mode React. While similar to `ReactDOM.createLegacyRoot`, it explicitly does not implement deprecated features like String Refs, Legacy Context, or `findDOMNode`. ```APIDOC ReactRoblox.createLegacyRoot Adopted as part of the Concurrent Mode API. "Legacy" roots are essentially equivalent to pre-concurrent React behavior. Refer to `ReactDOM.createLegacyRoot` documentation. Deviations: - String Refs: Never implemented in legacy Roact, and have not been ported. - Legacy Context: Never implemented in legacy Roact, and have not been ported. - findDOMNode: Never implemented in legacy Roact, and have not been ported. Instead, creating a Legacy Mode root simply tells Roact to render synchronously. This behavior is most similar to legacy Roact or pre-Concurrent-Mode React JS. Generally speaking, `ReactRoblox.createRoot` should be used for all new work, while the Blocking and Legacy versions can be used for upgrading existing Roact logic in the event that it does not yet meet the requirements for Concurrent Mode. ``` -------------------------------- ### React and Roact Functional setState Signature Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md This example illustrates the difference in `setState` updater function signatures between React and Roact. React's updater function has `this` in scope, while Roact's does not, encouraging pure functions for state updates. ```javascript this.setState((state, props) => { // `this` is in scope here and can be read from return {counter: state.counter + props.step}; }); ``` ```lua self:setState(function(state, props) -- `self` is NOT in scope here return { counter = state.counter + props } end); ``` -------------------------------- ### React.Profiler API Documentation Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react.md This entry refers to the official React Profiler API documentation for comprehensive details on its usage and functionality. ```APIDOC Refer to https://beta.reactjs.org/reference/react/Profiler ``` -------------------------------- ### React and Roact Uninitialized State Access Source: https://github.com/roblox/react-lua/blob/main/DEVIATIONS.md This example demonstrates how accessing uninitialized state behaves differently in React and Roact. In React, it throws a TypeError, while in Roact, it results in a nil value, leaving the UI element with its default value. ```javascript 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}
); } } ``` ```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 ``` -------------------------------- ### Clone Roact Alignment Repository and Analyze Project Source: https://github.com/roblox/react-lua/blob/main/README.md Clones the 'roact-alignment' repository from GitHub. The personal access token is used as the password during cloning. After navigating into the cloned directory, 'roblox-cli' is used to analyze the 'default.project.json' file. ```bash git clone https://github.com/Roblox/roact-alignment.git cd roact-alignment roblox-cli analyze default.project.json ``` -------------------------------- ### Test React-Lua TooltipButton Behavior with `act` Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/adopt-new-features.md Demonstrates an integration test for the `TooltipButton` component using `ReactRoblox.act`. It covers initial rendering, re-rendering, simulating user input (click), and waiting for delayed callbacks to ensure all state updates are flushed and component behavior is correctly validated. ```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) ``` -------------------------------- ### Clear Bash PATH Hash Cache for Rojo Source: https://github.com/roblox/react-lua/blob/main/README.md Updates bash's internal hash cache for executable paths. This command is specifically used to remove the cached location of a globally installed 'rojo' binary after it has been uninstalled, ensuring that the project uses the locally specified version. ```bash hash -d rojo ``` -------------------------------- ### Add Roact 17 Dependencies for New Rotriever Projects Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/upgrading-to-roact-17.md To integrate Roact 17 into a new project, add these entries to your `rotriever.toml` manifest file. This configures Rotriever to fetch `React` and `ReactRoblox` packages from the `roblox/roact-alignment` repository at version 17.0.1. ```toml [dependencies] React = "github.com/roblox/roact-alignment@17.0.1" ReactRoblox = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Roact 17: ReactRoblox.createPortal API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/convert-legacy-conventions.md Roact 17 introduces `ReactRoblox.createPortal` for creating portals, replacing the `Roact.Portal` component. This function is part of `ReactRoblox` as it interacts directly with Roblox Instances, maintaining renderer abstraction. ```APIDOC Function: ReactRoblox.createPortal(children: Roact.Element, container: Instance, key?: string) children: The Roact element(s) to render into the portal. container: The Roblox Instance (e.g., a ScreenGui, Frame) where the children will be mounted. key: An optional key for the portal. Replaces: Roact.Portal component Purpose: Allows rendering children into a DOM node that exists outside the hierarchy of the parent component. ``` -------------------------------- ### Mark Selected Code Block as Skipped Deviation (VSCode Snippet) Source: https://github.com/roblox/react-lua/blob/main/docs/align-files-guide.md Similar to `deviation-block`, this snippet comments out the selected code and wraps it with deviation START/END comments, but it does not insert a duplicated code block. It's specifically designed for blocks of code that should be entirely skipped or ignored. ```Lua -- ROBLOX deviation START: ${0:changed because} -- ${TM_SELECTED_TEXT/\n/\n-- /g} -- ROBLOX deviation END ``` ```JSON { "Deviation block - skip": { "prefix": "deviation-block-skipped", "body": [ "-- ROBLOX deviation START: ${0:changed because}", "-- ${TM_SELECTED_TEXT/\\n/\\n-- /g}", "-- ROBLOX deviation END" ], "description": "Roblox deviation end marker" } } ``` -------------------------------- ### Roact Stable Keys: Warning for Mixed Key Assignment Source: https://github.com/roblox/react-lua/blob/main/docs/deviations.md Shows an example where Roact will issue a warning because both a table key ('Label') and the special `key` prop ('label1') are used for the same element. Roact prioritizes the explicitly provided `key` prop in such cases, but warns about the ambiguity. ```lua return React.createElement("Frame", nil, { Label = React.createElement("TextLabel", { key = "label1", Text = "Hello", }) }) ``` -------------------------------- ### Configure Roact Alignment in rotriever.toml for new projects Source: https://github.com/roblox/react-lua/blob/main/README.md Add this line to your rotriever.toml file to consume the Roact Alignment library in a new project. ```TOML React = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Migrating from Legacy Context to createContext API Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/minimum-requirements.md Legacy Roact's `_context` field is deprecated and unsupported in Roact 17+. This section outlines the steps to replace `_context` usage with the modern Provider and Consumer pattern via `createContext`. This pattern allows Roact to trigger updates on context consumers when providers pass new values, and it is available in Roact 1.3.0+. ```APIDOC createContext(): ContextObject Description: Creates a new Context object. Returns: ContextObject - An object containing Provider and Consumer components. ContextObject.Provider: Component Props: value: any - The value to be provided to consuming components. Description: A Roact component that provides a context value to its descendants. ContextObject.Consumer: Component Props: render: function(contextValue: any): RoactElement - A function that receives the current context value and returns a Roact element. Description: A Roact component that subscribes to context changes. ``` -------------------------------- ### RoactCompat.act API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/roact-compat.md Provides compatibility by re-exporting ReactRoblox.act. ```APIDOC RoactCompat.act: Re-exports ReactRoblox.act ``` -------------------------------- ### Implementing a Reducer for Complex State with React.useReducer in Luau Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react.md This example demonstrates how to use the useReducer hook in Luau to manage complex state, such as a calculator's value and operation count. It defines a reducer function to handle different action types ('add', 'multiply') and shows how to dispatch actions from UI elements to update the 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 ``` -------------------------------- ### Roact 17: ReactRoblox.act API for Testing Concurrent Mode Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/adopt-new-features.md Details the `ReactRoblox.act` utility, essential for testing components when Concurrent Mode is enabled. It describes how `act` ensures tests function correctly by playing Roact's internal scheduler logic forward, and lists various scenarios that require wrapping in an `act` call, such as rendering updates, state changes, and user inputs. ```APIDOC ReactRoblox.act(callback: () => void): Promise Purpose: Utility to ensure tests relying on synchronous rendering behavior function correctly when Concurrent Mode is enabled. It runs the provided function, then performs queued Roact work by playing forward Roact's internal scheduler until the queue is empty. Parameters: callback: A function containing the code that triggers Roact updates (e.g., rendering, state changes, user inputs). Returns: A Promise that resolves when all queued work is complete. Usage Scenarios (wrap in act): - Rendering an initial tree with the `render` method of a React root or the `RoactCompat.mount` compatibility function. - Rendering updates with the `render` method of a React root. - Unmounting a tree by passing `nil` to the `render` method of a React root. - Calling `task.wait` or other yielding functions to allow engine callbacks to fire. - Triggering behavior that causes a component to update its state, including firing signals that your component has subscribed to. - Processing user inputs generated by Rhodium. Configuration: - To enable `act` function, set the `__ROACT_17_MOCK_SCHEDULER__` global to true in your testing configuration. - If `__ROACT_17_INLINE_ACT__` global is set to true, `mount`, `update`, and `unmount` will be automatically wrapped in `act`. ``` -------------------------------- ### Enable Roact Compatibility Warnings Source: https://github.com/roblox/react-lua/blob/main/docs/configuration.md Activates warnings for uses of outdated Roact APIs. This helps identify code that can be modernized to align with current standards and prepare for future releases, especially when migrating from Roact 1.x. ```APIDOC Global: __COMPAT_WARNINGS__ Type: boolean Description: Enables warnings for uses of outdated Roact APIs. Purpose: Helps identify and modernize code during migration from Roact 1.x, ensuring better alignment with current standards. Effect: Compatibility mismatches have no effect on behavior but can be updated. ``` -------------------------------- ### Accessing DOM Instances and Storing Mutable Values with React.useRef in Luau Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react.md useRef is a React Hook that provides a mutable object whose .current property can hold any value, persisting across renders without triggering re-renders. It's commonly used to get a direct reference to a Roblox Instance associated with a React element, enabling direct imperative interactions like programmatically focusing a TextBox. ```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 ``` -------------------------------- ### Configure Roact Compat in rotriever.toml for legacy code Source: https://github.com/roblox/react-lua/blob/main/README.md For projects with existing legacy Roact code, use this line in rotriever.toml to consume the roact-compat library. ```TOML RoactCompat = "github.com/roblox/roact-alignment@17.0.1" ``` -------------------------------- ### Replace Legacy Roact Dependency with Roact 17 Compat Source: https://github.com/roblox/react-lua/blob/main/docs/migrating-from-1x/upgrading-to-roact-17.md To upgrade an existing project from legacy Roact to Roact 17 while maintaining backward compatibility, modify your `rotriever.toml` file. This diff shows how to replace the old `Roact` dependency with `RoactCompat` from the `roact-alignment` package, aliasing it back to `Roact`. ```diff [dependencies] - Roact = "github.com/roblox/roact@1.4" + Roact = { target = "github.com/roblox/roact-alignment", version = "17.0.1", package = "RoactCompat" } ``` -------------------------------- ### Automatically Wrap Roact Compat Functions with act Source: https://github.com/roblox/react-lua/blob/main/docs/configuration.md Automatically wraps `RoactCompat.mount`, `RoactCompat.update`, and `RoactCompat.unmount` calls within `ReactRoblox.act`. This ensures queued actions are played forward by the mocked scheduler, useful for shoring up existing tests. ```APIDOC Global: __ROACT_17_INLINE_ACT__ Type: boolean Description: Automatically wraps RoactCompat.mount, RoactCompat.update, and RoactCompat.unmount calls within ReactRoblox.act. Purpose: Ensures that queued actions are processed by the mocked scheduler, aiding in the stability of existing tests. Dependency: Requires __ROACT_17_MOCK_SCHEDULER__ to be enabled. Usage: Intended for testing environments only. ``` -------------------------------- ### React 17 `unstable_createEventHandle` vs. Roact.Change/Event Source: https://github.com/roblox/react-lua/blob/main/modules/react-roblox/README.md Explains React 17's `unstable_createEventHandle` API for event listeners and contrasts it with Roact's existing `Roact.Change` and `Roact.Event`. Suggests avoiding translation and documenting the Roact equivalents. ```APIDOC unstable_createEventHandle API: React 17 exposes this API for managing event listeners on objects. Roact has its own approach via Roact.Change and Roact.Event. Decision: Avoid translating this logic; call it out in documentation for Change and Event. Consider adding a warning when accessing it that directs users to Change and Event documentation. ``` -------------------------------- ### ReactRoblox.act API Reference for Testing Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react-roblox.md Documents the `act` method, essential for testing ReactRoblox components with mocked scheduling logic. It ensures consistent test behavior by executing a function and then advancing the mock scheduler, and is enabled via a global flag in test environments. ```APIDOC ReactRoblox.act Used for testing code with scheduling logic mocked. This ensures that tests behave consistently and don't batch work unpredictably across frames. `act` executes a function and then plays forward the mock scheduler after it's done, and should be used to wrap any interactions that trigger updates to a roact UI. Deviations: In production, `ReactRoblox.act` will not be available. Set the global value `_G.__ROACT_17_INLINE_ACT__` to `true` in order to enable this behavior in tests. This behavior is still a work in progress, and there may be changes to how Roact detects whether or not it should provide the `act` function. For now, use the global `__ROACT_17_INLINE_ACT__` to enable it for tests. ``` -------------------------------- ### RoactCompat.Event API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/roact-compat.md Provides compatibility by re-exporting React.Event. ```APIDOC RoactCompat.Event: Re-exports React.Event ``` -------------------------------- ### RoactCompat.Change API Reference Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/roact-compat.md Provides compatibility by re-exporting React.Change. ```APIDOC RoactCompat.Change: Re-exports React.Change ``` -------------------------------- ### Create React Elements in Luau Source: https://github.com/roblox/react-lua/blob/main/docs/api-reference/react.md Shows how to use `React.createElement` to construct UI elements in Luau. Unlike React JS, Luau lacks JSX tooling, making direct `createElement` calls more common for defining component trees. ```lua --[[ React.createElement( type, [props], [...children] ) ]] local element = React.createElement( "Frame", { Size = UDim2.fromScale(1, 1) }, React.createElement("TextLabel", { Text = "Child1" }) React.createElement("TextLabel", { Text = "Child2" }) ) ``` -------------------------------- ### ReactRoblox Binding Creation and Joining Source: https://github.com/roblox/react-lua/blob/main/modules/react-roblox/README.md Demonstrates how to create and join bindings using the `ReactRoblox` API. Bindings are a Roact feature tightly coupled with refs, used for managing dynamic property updates. ```Lua ReactRoblox.createBinding(nil) ReactRoblox.joinBindings(binding1, binding2) ``` -------------------------------- ### Run Roact Alignment Tests with Roblox CLI Source: https://github.com/roblox/react-lua/blob/main/README.md Executes the project's tests using 'roblox-cli'. It specifies the test project model, the test runner script, and enables 'EnableLoadModule' and 'allOnLuau' fast flags to ensure the latest Luau language features and module state resetting are available for testing. ```bash roblox-cli run --load.model tests.project.json --run bin/spec.lua --fastFlags.overrides EnableLoadModule=true --fastFlags.allOnLuau ```