Components
Overview
Components are the building blocks of the user interface in your application. They are written in JSX in a very similar way to writing those in React and Solid. Function defining the component only runs once, and returns an HTML element that can be injected into the DOM and rendered. Components exported as default from pages are appended automatically to the DOM once the page is loaded. This guide assumes your familiarity with React and Solid and will not go into details about JSX.
Defining a Component
Components are mostly defined by declaring a function that returns a JSX element. The function is preferred to be given a name starting with an uppercase letter, otherwise there will be a restriction illustrated in the example below. It can also take in props in the form of a destructured object as an argument.
// Card.jsx // Here, the function is given a name starting with a lowercase letter. // Note how the props destructing must be preceded by '/** @ComponentProps */'. // The same applies to anonymous functions that have no name. const customAnchor = (/** @ComponentProps */ { href }) => ( <a href={href} target="_blank"> Learn more </a> ); export default function Card({ title, link, rounded, bgColor = "white", children, }) { const bgColorReporter = $createIEffect(() => { console.log(`Card's new background color is ${bgColor}.`); }); // Despite of the ability to define components using anonymous functions, // their names must start with a capital letter or a dollar sign ($) at usage time. const CustomAnchor = customAnchor; return ( <div border-radius={rounded ? "10px" : "0"} boxShadow="0 0 10px rgba(0, 0, 0, 0.2)" background-color="white" style={{ "display": "flex", "flex-direction": "column", "justifyContent": "flex-start", "alignItems": "center", }} onDestroy={() => $destroyEffect(bgColorReporter)} onDestroy={() => console.log("Card destroyed")} > <h2 style:fontWeight="bold">{title}</h2> {children} <CustomAnchor href={link}> Learn more </CustomAnchor> </div> ); }
Using a Component
Components in Mango are used in a similar way to React and Solid. Their names at usage time must start with a capital letter or a dollar sign ($) in case of defining a dynamic component through a state variable. Components may be defined locally, imported from other modules or even passed as properties from parent components to their children.
One of the most Mango-exclusive features is the ability to style the root element of the component or attach event listeners to it without the need to declare dedicated properties for this. This is made possible thanks to style
and event
namespaces.
// App.jsx import Card from "./Card.jsx"; export default function App() { let $cardBgColor = "white"; const toggleBgColor = () => { $cardBgColor = $cardBgColor === "white" ? "wheat" : "white"; }; return ( <div> <Card title="Hello World" link="https://google.com" rounded bgColor={$cardBgColor} style:color="black" event:onClick={toggleBgColor} event:onClick={() => console.log("Card clicked!")} > <p>Some content</p> </Card> </div> ); }
DOM Access
Mango provides a way to access the DOM of a component through the ref
property which takes a state variable as a value. Instance of the root element of the component is stored in the state variable. This makes DOM manipulation efficient and easy.
// App.jsx import Card from "./Card.jsx"; export default function App() { let $cardRef = null; const toggleBgColor = () => { $cardRef.style.backgroundColor = $cardRef.style.backgroundColor === "white" ? "wheat" : "white"; $cardRef.style.color = $cardRef.style.backgroundColor === "wheat" ? "brown" : "black"; }; return ( <div> <Card title="Hello World" link="https://google.com" rounded ref={$cardRef} event:onClick={toggleBgColor} > <p>Some content</p> </Card> </div> ); }
Elements can also have a ref
attribute which works in a similar way to the ref
property of the component. The difference is that the state variable will store the instance of the element itself instead of the root element of the component.
// App.jsx export default function App() { let $cardRef = null; const toggleBgColor = () => { $cardRef.style.backgroundColor = $cardRef.style.backgroundColor === "white" ? "wheat" : "white"; $cardRef.style.color = $cardRef.style.backgroundColor === "wheat" ? "brown" : "black"; }; return ( <div> <div ref={$cardRef} event:onClick={toggleBgColor}> <p>Some content</p> </div> </div> ); }