### Install ReasonReact Dependencies with Opam Source: https://reasonml.github.io/reason-react/docs/en/installation Installs the necessary native dependencies for ReasonReact development using the opam package manager. This includes Melange, Dune, Reason, and ReasonReact with its PPX extension. ```bash opam install melange dune reason reason-react reason-react-ppx -y ``` -------------------------------- ### Clone and Initialize ReasonReact Melange Template Source: https://reasonml.github.io/reason-react/docs/en/installation This snippet demonstrates how to clone the official Melange opam template for ReasonReact, initialize dependencies, and run watch and serve commands for development. ```bash # clone the repo git clone https://github.com/melange-re/melange-opam-template my-reason-react-app # This will initialise the opam switch and install all the dependencies (from both opam and npm) cd my-reason-react-app && npm run init # We install native dependencies (melange, dune, reason and reason-react) from opam # while JavaScript dependencies (react, react-dom, webpack) from npm # In separate terminals: npm run watch # It will watch for changes in your Reason/OCaml files and compile them to JavaScript npm run serve # Serves the application with a local HTTP server ``` -------------------------------- ### Install ReasonReact and reason-react-ppx using opam Source: https://reasonml.github.io/reason-react/blog Instructions for installing the latest versions of ReasonReact and reason-react-ppx using the opam package manager. This ensures you have the necessary tools for ReasonReact development. ```bash opam update opam install reason-react reason-react-ppx ``` -------------------------------- ### Build ReasonReact Code with Dune Source: https://reasonml.github.io/reason-react/docs/en/installation Commands to build ReasonReact code using Dune. It shows how to build a specific target and how to enable watch mode for automatic recompilation on file changes. ```bash # "@melange" is an alias created automatically from the target field in the dune file opam exec -- dune build @melange # or if you want to watch for changes opam exec -- dune build @melange --watch ``` -------------------------------- ### ReasonReact Simple Counter Example with useState Source: https://reasonml.github.io/reason-react/docs/en/usestate-hook A basic example demonstrating the usage of the useState hook to create a counter component in ReasonReact. It shows how to initialize state and update it using buttons. ```reasonml [@react.component] let make = (~initialCount) => { let (count, setCount) = React.useState(_ => initialCount);
{React.string("Count: " ++ Int.to_string(count))}
; }; ``` -------------------------------- ### Opam Package Definitions for React Dependencies Source: https://reasonml.github.io/reason-react/blog/2023/09/13/reason-react-ppx This example demonstrates how to specify external npm dependencies for React and React-DOM using opam's depexts. This ensures that the correct versions of these libraries are installed when managing project dependencies. ```opam depexts: [ [ "react" ] {npm-version = "^16.0.0 || ^17.0.0"} [ "react-dom" ] {npm-version = "^16.0.0 || ^17.0.0"} ] ``` -------------------------------- ### ReasonReact useEffect Cleanup Example Source: https://reasonml.github.io/reason-react/docs/en/useeffect-hook Demonstrates how to use `useEffect0` in ReasonReact to set up a subscription and clean it up when the component unmounts. This is useful for preventing memory leaks. ```reasonml [@react.component] let make = () => { React.useEffect0(() => { let id = subscription.subscribe(); /* clean up the subscription */ Some(() => subscription.unsubscribe(id)); }); } ``` -------------------------------- ### Install ReasonReact with opam Source: https://reasonml.github.io/reason-react/blog/2023/06/11/reborn Installs the latest version of ReasonReact using the opam package manager. This is the first step to adopting ReasonReact in a Melange project. ```bash opam install reason-react ``` -------------------------------- ### ReasonReact ReactDOM Client Rendering Example Source: https://reasonml.github.io/reason-react/docs/en/dom Demonstrates how to use ReactDOM.Client.createRoot and ReactDOM.Client.render to render a React element into the DOM using ReasonReact. This replaces the older ReactDOM.render function in React 18. It handles cases where the target element might not be found. ```reasonml let element = ReactDOM.querySelector("#root"); switch (element) { | None => Js.log("#root element not found"); | Some(element) => { let root = ReactDOM.Client.createRoot(element); ReactDOM.Client.render(, root); } } ``` -------------------------------- ### ReasonReact Component Example (ReasonML) Source: https://reasonml.github.io/reason-react/ja A basic ReasonReact component demonstrating how to define a functional component using the 'react.component' attribute. It takes a 'name' prop and renders a button with a greeting. ```reasonml [@react.component] let make = (~name) => ; ``` -------------------------------- ### Basic Greeting Component in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/simple Demonstrates creating a basic ReasonReact component named 'Greeting' that accepts a 'message' prop and renders it within an h1 tag. It highlights Reason's implicit return, labeled parameters, and type casting with React.string. ```reasonml /* Greeting.re */ [@react.component] let make = (~message) =>

{React.string(message)}

; ``` ```javascript /* ... */
/* ... */ ``` -------------------------------- ### Component with Optional Arguments and Fragment in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/simple Illustrates a ReasonReact component that accepts an optional 'description' argument. It uses React.Fragment (<>) and demonstrates conditional rendering based on the presence of the description, including the necessity of React.null for None cases. ```reasonml [@react.component] let make = (~title, ~description=?) => <> /* React.Fragment works the same way as in React.js! */

title

/* Handling optional variables where you don't want to render anything */ { switch (description) { | Some(description) => {React.string(description)} /* Since everything is typed, React.null is required */ | None => React.null } } ; ``` -------------------------------- ### Configure Dune for Melange Integration Source: https://reasonml.github.io/reason-react/docs/en/installation Configures the Dune build system to use Melange for compiling Reason/OCaml code to JavaScript. This involves specifying the Dune language version and enabling the Melange compiler. ```dune (lang dune 3.8) (using melange 0.1) ``` -------------------------------- ### ReasonReact useReducer Example Source: https://reasonml.github.io/reason-react/docs/en/usereducer-hook Demonstrates the useReducer hook in ReasonReact for managing complex state logic. It defines action types, a reducer function, and a React component that utilizes the hook to update state based on user interactions. This approach is preferable to useState for intricate state management and performance optimization. ```reasonml /* we can create anything as the type for action, here we use a variant with 2 cases. */ type action = | Increment | Decrement; /* `state` could also be anything. In this case, we want an int */ let reducer = (state, action) => switch (action) { | Increment => state + 1 | Decrement => state - 1 }; [@react.component] let make = (~initialValue=0) => { let (state, dispatch) = React.useReducer(reducer, initialValue);
state->React.int
; }; ``` -------------------------------- ### Basic ReasonReact Component Test with ReactDOMTestUtils Source: https://reasonml.github.io/reason-react/docs/en/testing Demonstrates a basic test case for a ReasonReact component using `ReactDOMTestUtils` and an imaginary `TestFramework` binding. It covers setting up a DOM container, rendering a component using `act`, and asserting its presence via DOM querying. This example assumes `TestFramework` provides `describe`, `test`, `beforeEach`, and `afterEach` functions, similar to Jest. ```reason open ReactDOMTestUtils; open TestFramework; // TestFramework isn't a real module, just an imaginary set of bindings // to a JavaScript testing framework describe("My basic test", ({test, beforeEach, afterEach}) => { // Here, we prepare an empty ref that will eventually be // the root node for our test let container = ref(None); // Before each test, creates a new div root beforeEach(prepareContainer(container)); // After each test, removes the div afterEach(cleanupContainer(container)); test("can render DOM elements", ({expect}) => { // The following function gives us the div let container = getContainer(container); let root = ReactDOM.Client.createRoot(container); // Most of the ReactDOMTestUtils API is there act(() => { ReactDOM.Client.render(root,
"Hello world!"->React.string
); }); expect.bool( container // We also provide some basic DOM querying utilities // to ease your tests ->DOM.findBySelectorAndTextContent("div", "Hello world!") ->Option.isSome, ). toBeTrue(); }); }); ``` -------------------------------- ### Render ReasonReact Component in Plain JavaScript Source: https://reasonml.github.io/reason-react/docs/en/intro-example Shows the equivalent way to render a React component in plain JavaScript, as a comparison to the ReasonML rendering example. This snippet uses standard JavaScript DOM manipulation and ReactDOM.render. ```javascript /* file: index.js */ let root = document.getElementById("root"); if (root != null) { ReactDOM.render(, root); }; ``` -------------------------------- ### ReasonReact JSX with Children Example Source: https://reasonml.github.io/reason-react/docs/en/components Shows how to use the 'ComponentTakesChildren' component in ReasonReact JSX, passing a 'name' prop and providing JSX elements as children. This demonstrates the practical usage of components that handle children. ```reason
{React.string("Effectively the child.")}
``` -------------------------------- ### Form Component with Event Handling in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/simple Shows how to create a form component in ReasonReact, including handling form submission and input elements. It covers underscore prefixing for unused variables, shorthand for event props, and Reason-specific syntax like 'type_' for reserved words and the absence of braces for boolean props. ```reasonml [@react.component] let make = () => { /* unused variables are prefixed with an underscore */ let onSubmit = _event => Js.log("Hello this is a log!"); /* onSubmit=onSubmit turns to just onSubmit */
; }; ``` -------------------------------- ### List Rendering Component with Belt in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/simple Demonstrates rendering a list of items in ReasonReact using the Belt library. It defines a record type for list items and uses Belt.Array.map to transform the items into React list elements, emphasizing the type casting required for arrays with ->React.array. ```reasonml /* We define the type of the item (this is a record) */ type item = { id: string, text: string, }; [@react.component] let make = (~items) => ; ``` -------------------------------- ### ReasonReact ReactDOM Hydration Example Source: https://reasonml.github.io/reason-react/docs/en/dom Shows how to use ReactDOM.Client.hydrateRoot for hydration in ReasonReact, which is the process of making a static HTML page interactive with React. It renders a React element onto an existing DOM element, typically used for server-rendered applications. ```reasonml let element = ReactDOM.querySelector("#root"); switch (element) { | None => Js.log("#root element not found"); | Some(element) => { /* root is a ReactDOM.Client.root and used to render on top of the existing HTML with ReactDOM.Client.render or unmount, via ReactDOM.Client.unmount. */ let _root = ReactDOM.Client.hydrateRoot(, element); (); } } ``` -------------------------------- ### ReasonReact useEffect Conditional Firing Example Source: https://reasonml.github.io/reason-react/docs/en/useeffect-hook Illustrates using `useEffect1` in ReasonReact to conditionally fire an effect based on changes in a source value. The effect re-runs only when the specified dependencies change, optimizing performance. ```reasonml [@react.component] let make = (~source) => { React.useEffect1(() => { let id = subscription.subscribe(); /* clean up the subscription */ Some(() => subscription.unsubscribe(id)); }, [|source|]); } ``` -------------------------------- ### Conditional Rendering Based on URL Hash and Application State Source: https://reasonml.github.io/reason-react/docs/en/router An example showcasing how to combine URL hash matching with application state (like user login status) to conditionally render different UI elements or states within a ReasonReact component. ```reason [@react.component] let make = () => { let url = ReasonReactRouter.useUrl(); let nowShowing = switch (url.hash, MyAppStatus.isUserLoggedIn) { | ("active", _) => Active | ("completed", _) => Completed | ("shared", true) => Shared | ("shared", false) when isSpecialUser => /* handle this state please */ | ("shared", false) => /* handle this state please */ | _ => All }; /* ... */ } ``` -------------------------------- ### ReasonReact Component with Hooks (useReducer, useEffect0) Source: https://reasonml.github.io/reason-react/blog/2019/04/10/react-hooks An example of a ReasonReact component utilizing React Hooks. It demonstrates state management with `React.useReducer` and side effect handling with `React.useEffect0`, including setting up and cleaning up an interval timer. ```reasonml type action = [ Tick ]; type state = { count: int }; [@react.component] let make = () => { let (state, dispatch) = React.useReducer( (state, action) => switch (action) { | Tick => {count: state.count + 1} }, {count: 0} ); React.useEffect0(() => { let timerId = Js.Global.setInterval(() => dispatch(Tick), 1000); Some(() => Js.Global.clearInterval(timerId)) });
{ReasonReact.string(string_of_int(state.count))}
; }; ``` -------------------------------- ### Define Melange Compilation Target in Dune Source: https://reasonml.github.io/reason-react/docs/en/installation Defines a Dune stanza for Melange compilation. It specifies the output target name, the libraries to link against (including reason-react), and the preprocessor extensions to use. ```dune (melange.emit (target melange) ; or any target name you want (libraries reason-react) (preprocess (pps reason-react-ppx))) ``` -------------------------------- ### Invalid GraphQL Query Example with graphql-ppx Source: https://reasonml.github.io/reason-react/docs/en/graphql-apollo This snippet shows an example of an invalid GraphQL query that would cause a compile-time error with graphql-ppx. The error occurs because the field 'namee' does not exist on the 'currentUser' type, as defined in the graphql_schema.json. ```reasonml /* Username.re */ module UserQuery = [%graphql {| query UserQuery { currentUser { namee // ERROR: Unknown field on type currentUser } } |}]; ``` -------------------------------- ### Configure Dune File for ReasonReact Source: https://reasonml.github.io/reason-react/blog/2023/09/13/reason-react-ppx This snippet shows how to configure your dune file to include ReasonReact as a library and reason-react-ppx for preprocessing. Ensure these settings are correctly applied for ReasonReact to function with your project. ```ocaml (libraries reason-react) (preprocess (pps reason-react-ppx)) ``` -------------------------------- ### Render ReasonReact Component in ReasonML App Source: https://reasonml.github.io/reason-react/docs/en/intro-example Demonstrates how to render the 'Greeting' ReasonReact component within a ReasonML application's entry point. It uses ReactDOM.render to attach the component to a DOM element. This snippet shows the ReasonML way of rendering. ```reasonml /* file: Index.re */ switch (ReactDOM.querySelector("#root")) { | Some(root) => ReactDOM.render(, root) | None => () } ``` -------------------------------- ### Passing Components as Props in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/component-as-prop Demonstrates how to pass components as props in ReasonReact, a common pattern when migrating from ReactJS. It involves defining a callback function that renders the target component with its props. ```reasonml let bannerCallback = (prop1, prop2) => ; ; ``` -------------------------------- ### Matching Routes with Pattern Matching in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/router Demonstrates how to use Reason's powerful pattern matching to handle different URL structures and extract relevant information for routing logic within a React component. ```reason let url = ReasonReactRouter.useUrl(); switch (url.path) { | ["book", id, "edit"] => handleBookEdit(id) | ["book", id] => getBook(id) | ["book", id, _] => noSuchBookOperation() | [] => showMainPage() | ["shop"] | ["shop", "index"] => showShoppingPage() | ["shop", ...rest] => /* e.g. "shop/cart/10", but let "cart/10" be handled by another function */ nestedMatch(rest) | _ => showNotFoundPage() }; ``` -------------------------------- ### Create and Provide ReasonReact Context Source: https://reasonml.github.io/reason-react/docs/en/context This snippet demonstrates how to create a context object using `React.createContext` and then create a provider component for that context. The provider component can be defined either in a separate file or within another module. It uses `React.Context.provider` to create the component. ```reasonml /** as a separate file: ContextProvider.re */ // 1. The context itself let themeContext = React.createContext("light"); // 2. The provider include React.Context; // Adds the makeProps external let make = React.Context.provider(themeContext); ``` ```reasonml /** or inside any other module */ // 1. The context itself let themeContext = React.createContext("light"); // 2. The provider component module ContextProvider = { include React.Context; // Adds the makeProps external let make = React.Context.provider(themeContext); }; ``` -------------------------------- ### Bind to External JavaScript Context in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/context This example demonstrates how to bind to a React context defined in an external JavaScript file. It uses `bs.module` to import the context and then uses `React.useContext` to consume its value within a ReasonReact component. ```javascript /** ComponentThatDefinesTheContext.js */ export const ThemeContext = React.createContext("light"); ``` ```reasonml /** ComponentToConsumeTheContext.re */ [@bs.module "ComponentThatDefinesTheContext"] external themeContext: React.Context.t(string) = "ThemeContext"; [@react.component] let make = () => { let theme = React.useContext(themeContext);

theme->React.string

} ``` -------------------------------- ### Import Basic Reason File to JavaScript (ReasonReact) Source: https://reasonml.github.io/reason-react/docs/en/importing-reason-into-js Demonstrates how to import a basic ReasonML component defined in a `.re` file into a JavaScript file (`.js`). It shows the standard way of importing named exports generated by the BuckleScript compiler. ```reason /* Greeting.re */ [@react.component] let make = (~name) => {React.string("Hey " ++ name)} ; ``` ```javascript /* App.js */ import { make as Greeting } from './Greeting.bs' export default function App() { return } ``` -------------------------------- ### URL Structure and Matching Source: https://reasonml.github.io/reason-react/docs/en/router Defines the structure of the `url` record provided by the router and demonstrates how to match routes using ReasonML's pattern matching. ```APIDOC ## URL Structure and Matching ### URL Record Structure The `url` record represents the current state of the browser's location, parsed into usable components: ```reason type url = { path: list(string), hash: string, search: string }; ``` * **`path`**: An array of strings representing the pathname, e.g., `"/book/10/edit"` becomes `["book", "10", "edit"]`. * **`hash`**: The URL's hash fragment (part after `#`), with the `#` symbol removed. * **`search`**: The URL's query string (part after `?`), with the `?` symbol removed. **Example**: For the URL `www.hello.com/book/10/edit?name=Jane#author`, the `url` record would be: ```reason { path: ["book", "10", "edit"], hash: "author", search: "name=Jane" } ``` ### Route Matching with Pattern Matching ReasonML's powerful pattern matching allows for flexible and expressive route handling: ```reason [@react.component] let make = () => { let url = ReasonReactRouter.useUrl(); let view = switch (url.path) { | ["book", id, "edit"] => HandleBookEdit(id) | ["book", id] => GetBook(id) | ["book", id, _] => NoSuchBookOperation() | [] => ShowMainPage() | ["shop"] | ["shop", "index"] => ShowShoppingPage() | ["shop", ...rest] => NestedShopLogic(rest) | _ => ShowNotFoundPage() };
{ReasonReact.string("Current View: ") ++ view}
}; ``` This example demonstrates matching exact paths, sub-paths, and using the `...rest` syntax for nested routing logic. You can also combine URL matching with other state, like user login status, using nested switches or `if` conditions within the match cases: ``` -------------------------------- ### ReasonReact Component for ReactJS Source: https://reasonml.github.io/reason-react/docs/en/js-using-reason This snippet demonstrates how to define a React component using ReasonReact. It takes a 'message' prop and an optional 'extraGreeting' prop. The component renders a 'MyBannerRe' component with a combined message. The generated JavaScript can be imported and used in a ReactJS application. ```reason /* ReasonReact used by ReactJS */ [@react.component] let make = (~message, ~extraGreeting=?) => { let greeting = switch (extraGreeting) { | None => "How are you?" | Some(g) => g };
; }; ``` ```javascript var PageReason = require('path/to/PageReason.js').make; ``` -------------------------------- ### ReactJS useState with Event Handling (for comparison) Source: https://reasonml.github.io/reason-react/docs/en/usestate-hook Illustrates a common pattern in ReactJS for handling input changes using the useState hook and an onChange event handler. ```javascript /* App.js */ function App() { const [name, setName] = React.useState("John"); return ( setName(event.target.value)} /> ); } ``` -------------------------------- ### Using Apollo Client with graphql-ppx in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/graphql-apollo This snippet illustrates how to use Apollo Client hooks (useQuery) with a type-safe GraphQL query defined by graphql-ppx in ReasonReact. It shows how to handle different query states (Loading, Data, Error) using Reason's pattern matching and idiomatic variant handling, ensuring both Reason and GraphQL type safety. ```reasonml /* Username.re */ module UserQuery = [%graphql {| query UserQuery { currentUser { name } } |}]; [@react.component] let make = () => { let (currentUserName, _) = ApolloHooks.useQuery(UserQuery.definition);
{ switch(currentUserName) { | Loading =>

{React.string("Loading...")}

| Data(data) =>

{React.string(data##currentUser##name)}

| NoData | Error(_) =>

{React.string("Get off my lawn!")}

} }
} ``` -------------------------------- ### Use Spread Component to Add data-* Attributes in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/adding-data-props This ReasonReact example demonstrates how to use the 'Spread' component to add a 'data-cy' attribute to a div element. The 'Spread' component accepts a 'props' record containing the desired attribute and its value, and then renders the 'children' with these attributes applied. ```reason [@react.component] let make = () => /* This div will now have the `data-cy` attribute in the DOM! */
; ``` -------------------------------- ### Wrap Component Tree with ReasonReact Context Provider Source: https://reasonml.github.io/reason-react/docs/en/context This code shows how to use the `ContextProvider` component created previously to wrap a part of the component tree. Any child component within this `ContextProvider` will have access to the context value passed via the `value` prop. ```reasonml /** App.re */ [@react.component] let make = () =>
``` -------------------------------- ### ReasonReact ReactDOMServer Rendering to String Source: https://reasonml.github.io/reason-react/docs/en/dom Illustrates the usage of ReactDOMServer.renderToString from ReasonReact, which is equivalent to React-DOM/server's renderToString. It takes a React element and returns its HTML representation as a string. ```reasonml /* Example usage of renderToString */ let htmlString = ReactDOMServer.renderToString(); ``` -------------------------------- ### cloneElement Function in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/clone-element Demonstrates the usage of the cloneElement function in ReasonReact, which is analogous to ReactJS's cloneElement. It shows how to clone an element and add props, while also warning about the unsafety of the props value and discouraging prop spreading simulation. ```reasonml let clonedElement = React.cloneElement(
, ~props={"payload": 1}, [||]); ``` -------------------------------- ### Handling URL Changes Manually Source: https://reasonml.github.io/reason-react/docs/en/router Explains how to manually update the URL and trigger the necessary events for the router to detect the changes. ```APIDOC ## Handling URL Changes Manually ### Pushing a New Route To navigate to a new route programmatically, use the `ReasonReactRouter.push` function: ```reason ReasonReactRouter.push("/books/10/edit#validated"); ``` This function updates the browser's URL using the `History API` (`pushState`) and then dispatches a custom `"popState"` event. This event is what `ReasonReactRouter.useUrl` listens for, ensuring that components re-render with the new URL information. ### Manually Triggering URL Change Detection If you modify the URL directly using methods other than `ReasonReactRouter.push` (e.g., in an incremental migration scenario), you must manually dispatch a `"popState"` event for the router to recognize the change: ```reason // After manually changing window.location.href or using pushState window.dispatchEvent(new Event('popState')); ``` This ensures that the `useUrl` hook and any other watchers are notified of the URL alteration. ``` -------------------------------- ### Configure ReasonReact in dune file Source: https://reasonml.github.io/reason-react/blog/2023/06/11/reborn Configures the dune build system to include ReasonReact as a library and use the reactjs-jsx-ppx preprocessor for JSX syntax. This is a required step for using ReasonReact. ```dune (libraries reason-react) (preprocess (pps react-jsx-ppx)) ``` -------------------------------- ### Define a ReasonReact Component: Greeting Source: https://reasonml.github.io/reason-react/docs/en/intro-example Defines a simple ReasonReact functional component named 'Greeting' that accepts a 'name' prop and renders a button with a personalized greeting. This component is written in ReasonML. ```reasonml /* file: Greeting.re */ [@react.component] let make = (~name) => ; ``` -------------------------------- ### Basic Render Props in ReasonReact Source: https://reasonml.github.io/reason-react/docs/en/render-props Demonstrates a basic implementation of Render Props in ReasonReact. The `Loader` component accepts a `render` prop, which is a function that returns a React element. This pattern is useful for sharing stateful logic between components. ```reasonreact [@react.component] let make = () => {
} /> }; ``` ```reason /* Loader.re */ [@react.component] let make = (~render) => {
{render()}
}; ``` -------------------------------- ### Define a React Component with ReasonReact Source: https://reasonml.github.io/reason-react/pt-BR This snippet demonstrates how to define a basic React component named 'make' using ReasonReact's [@react.component] decorator. The component accepts a 'name' prop and renders a button that displays a greeting. It leverages React.string for rendering text within the button. ```reasonml [@react.component] let make = (~name) => ; ``` ```reasonml [@react.component] let make = (~name) => ``` -------------------------------- ### ReasonReact Ternary Shortcut Source: https://reasonml.github.io/reason-react/docs/en/ternary-shortcut Illustrates the ReasonReact equivalent of ReactJS's ternary shortcut pattern. It shows how to conditionally render elements using the `? : React.null` syntax, which is necessary in ReasonReact unlike the `&&` operator in JavaScript. ```reason showButton ?