Hooks
Hooks are functions that let you use state and other Fluxus features in functional components. This section covers the built-in hooks and how to create custom hooks.
Overview
Hooks were introduced to solve several problems in component-based UI libraries:
- Reusing stateful logic between components without complex patterns
- Splitting components into smaller functions based on related pieces
- Using state without writing class components
In Fluxus, hooks are implemented using a simple index-based system that tracks hook calls within each component instance.
Rules of Hooks
To ensure hooks work correctly, you must follow these rules:
-
Only call hooks at the top level of your component functions. Don’t call hooks inside loops, conditions, or nested functions.
-
Only call hooks from Fluxus component functions. Don’t call them from regular Scala functions.
The reason for these rules is that Fluxus relies on the order of hook calls to maintain each hook’s state across renders.
Basic Example
Here’s a simple example using the useState
hook:
val Counter = () => {
val (count, setCount, _) = useState(0)
div(
p(s"Count: $count"),
button(
onClick := (() => setCount(count + 1)),
"Increment"
)
)
}
Available Hooks
Fluxus provides several built-in hooks:
- useState: Adds local state to a function component
- useEffect: Performs side effects in function components
- useRef: Creates a mutable reference that persists across renders
- useMemo: Memoizes expensive computations
- useCallback: Memoizes callback functions
- useFetch: Fetches data from a server
- useSignal: Integrates with Airstream for reactive programming
Creating Custom Hooks
You can create your own hooks to reuse stateful logic between components. A custom hook is simply a function that calls other hooks.
def useFormField(initialValue: String): (String, dom.Event => Unit, Boolean) = {
val (value, setValue, _) = useState(initialValue)
val (touched, setTouched, _) = useState(false)
val handleChange = (e: dom.Event) => {
setValue(e.target.asInstanceOf[dom.html.Input].value)
setTouched(true)
}
(value, handleChange, touched)
}
By convention, custom hook names should start with “use” to make it clear they follow the rules of hooks.
Next Steps
Explore each hook in detail in the following pages, starting with useState.