Functional Components and Hooks
Slinky supports writing components as functional components, where the definition is simply a function from props to the elements to render. This style is also the foundation for React Hooks, an new style of writing components that significantly reduces the boilerplate involved.
Writing a Functional Component
To write a functional component, create an instance of the FunctionalComponent
class.
To generate a friendly .apply
method like with the @react class
style, you can place the @react
annotation on an object that contains a case class Props
and property val component
which is a functional component.
Using React Hooks
Slinky supports all the React Hooks, with APIs that are almost identical versions of the ones included in React with additional typesafety. To learn more about the available hooks, take a look at the official React docs. The purpose of this section is to highlight the differences between the React and Slinky APIs.
To use hooks, import them from the Hooks
object and use them in your functional component just like you would in regular React code:
Some hooks, like useEffect
, useCallback
, useMemo
, and useLayoutEffect
, can take an extra list of objects that determines whether values should be recalculated. In Slinky, this list can be any iterable Scala collection, such as a Seq
. For example, the usage of useEffect
with watched values would look like:
Forwarding Refs
React includes the React.forwardRef
function to allow functional components to take refs. In Slinky, forwardRef
can be used by calling it on a FunctionalComponentTakingRef
, a special version of FunctionalComponent
that can be created by passing in a function taking two parameters -- the regular props parameter as well as the ref (of type ReactRef
).
When using hooks, forwardRef
can be used to expose an imperative API with the useImperativeHandle
hook. The ref type passed into FunctionalComponent[...]
determines what APIs will be available on the ref, so Scala traits work well here to expose custom imperative functions. For example, to expose a .bump()
method on the ref of a functional component: