Components
Components are the building blocks of Fluxus applications. They encapsulate rendering logic, state, and behavior into reusable pieces.
Component Types
In Fluxus, there is a single component type - function components. These are simple functions that take props and return a FluxusNode
.
Function Components
Function components are defined as functions that accept a Props
type parameter and return a FluxusNode
:
case class UserProps(name: String, age: Int)
val UserProfile = (props: UserProps) => {
div(
cls := "user-profile",
h2(s"${props.name}"),
p(s"Age: ${props.age}")
)
}
Using Components
To use a component, you call it with the <>
operator and its props:
UserProfile <> UserProps("John Doe", 30)
For components that don’t need props, you can use the NoProps
type:
val Header = (_: NoProps) => {
header(
cls := "app-header",
h1("My Application")
)
}
// Usage
Header <> noProps
Alternatively, you can define a component that takes Unit
:
val Footer = () => {
footer(
p("© 2025 My Company")
)
}
// Usage
Footer <> ()
Composing Components
Components can be composed to build more complex UIs:
case class AppProps(user: User)
val App = (props: AppProps) => {
div(
cls := "app",
Header <> noProps,
UserProfile <> UserProps(props.user.name, props.user.age),
Footer <> ()
)
}
Component Props
Props (short for “properties”) are the inputs to a component. In Fluxus, props are defined as case classes:
case class ButtonProps(
label: String,
onClick: () => Unit,
disabled: Boolean = false,
variant: String = "primary"
)
This provides type safety and makes it clear what props a component expects.
Keys
When rendering lists of components, it’s important to provide a key
property to help Fluxus identify which items have changed, been added, or been removed:
case class TodoItemProps(
key: String, // Including key in the props is recommended
text: String,
completed: Boolean,
onToggle: () => Unit
)
val TodoList = (props: TodoListProps) => {
ul(
cls := "todo-list",
props.items.map(item =>
TodoItem <> TodoItemProps(
key = item.id,
text = item.text,
completed = item.completed,
onToggle = () => props.onToggle(item.id)
)
)
)
}
Refs and Component References
Fluxus supports forwarding refs to components using the forwardRef
function:
case class CustomInputProps(
label: String,
placeholder: String = ""
)
val CustomInput = forwardRef[CustomInputProps] { (props, ref) =>
div(
cls := "form-control",
label(props.label),
input(
typ := "text",
placeholder := props.placeholder,
ref := ref
)
)
}
// Usage
val inputRef = useRef[dom.html.Input]()
CustomInput <> (CustomInputProps("Username", "Enter username"), inputRef)
// Later you can access the DOM element
inputRef.current.focus()
Component Best Practices
-
Keep components focused: Each component should ideally do one thing well.
-
Props should be immutable: Treat props as immutable values.
-
Use hooks for state: For components that need state, use hooks like
useState
rather than storing state outside the component. -
Extract complex logic: If a component gets too complex, extract parts into separate components or custom hooks.
-
Naming conventions: Use PascalCase for component names and camelCase for props and local variables.
-
Don’t modify props: Treat props as read-only. If you need to modify a value, create local state based on the prop.
-
Pure rendering: Component rendering should be a pure function of props and state, without side effects.