useFacetCallback
The useFacetCallback hook is similar to React's useCallback in that it allows you to create a memoized callback that will only be updated if some of the explicit dependencies change. On top of that, useFacetCallback allows you to pass one or more Facets and get the current values of those facets in the callback body.
Like useCallback, useFacetCallback will update the reference if a value in the dependency array change. However, it will not update the reference if a Facet change.
Signature
The useFacetCallback hook has two overloads depending on whether a defaultReturn is provided:
With defaultReturn (guaranteed return value):
typescriptuseFacetCallback<M>(callback: (...facetValues) => (...args) => M,dependencies: unknown[],facets: Facet[],defaultReturn: M): (...args) => M
Without defaultReturn (may return NO_VALUE):
typescriptuseFacetCallback<M>(callback: (...facetValues) => (...args) => M,dependencies: unknown[],facets: Facet[]): (...args) => M | NoValue
Parameters:
callback: Function that receives facet values and returns a callback functiondependencies: Non-facet dependencies (props, local variables)facets: Array of facets whose values the callback depends ondefaultReturn: (Optional) Value to return if any facet is uninitialized (NO_VALUE). When provided, the return type is guaranteed to beM. When omitted, the return type isM | NoValue.
Returns:
- When
defaultReturnis provided: A memoized callback function that returnsM - When
defaultReturnis omitted: A memoized callback function that returnsM | NoValue
Basic Usage
Say for example that you have a small form, and want to create a handler for the Submit action. You need to have access to the current value of a facet that stores the value of an input field in order to send that value back to the parent component when the Submit button of the form. useFacetCallback allows you to create such handler, which will always have access to the current value of the facet.
tsximport {useCallback } from 'react'import {useFacetState ,useFacetCallback } from '@react-facet/core'constForm = ({onSubmit ,initialValue }:Props ) => {const [value ,setValue ] =useFacetState (initialValue )consthandleChange =useCallback <KeyboardCallback >((event ) => {if (event .target instanceofHTMLInputElement ) {setValue (event .target .value )}},[setValue ],)consthandleClick =useFacetCallback ((currentValue ) => () => {onSubmit (currentValue )},[onSubmit ],[value ],)return (<fast-div ><fast-input onKeyUp ={handleChange }value ={value } /><fast-div onClick ={handleClick }>Submit</fast-div ></fast-div >)}
Using defaultReturn
The defaultReturn parameter allows you to specify a return value for the callback when facets are not yet initialized. This is the value that will be returned when the callback is invoked before all facets have values.
tsximport {useFacetState ,useFacetCallback } from '@react-facet/core'constScoreDisplay = () => {const [scoreFacet ,setScore ] =useFacetState (0)// Calculate bonus points based on score// Returns a number, so defaultReturn should be a numberconstcalculateBonus =useFacetCallback ((score ) => () => {if (score > 100) returnscore * 0.1if (score > 50) returnscore * 0.05return 0},[],[scoreFacet ],0, // Default return value when scoreFacet is not initialized)return (<div ><button onClick ={() => {constbonus =calculateBonus ()console .log ('Bonus points:',bonus )}}>Calculate Bonus</button ></div >)}
Another example with a different return type:
tsximport {useFacetState ,useFacetCallback } from '@react-facet/core'constUserGreeting = () => {const [userFacet ] =useFacetState ({name : 'Alice',isAdmin : false })// Returns a string, so defaultReturn is a stringconstgetGreeting =useFacetCallback ((user ) => () => {returnuser .isAdmin ? `Welcome back, Admin ${user .name }!` : `Hello, ${user .name }!`},[],[userFacet ],'Welcome, Guest!', // Default greeting when userFacet is not initialized)return <div >{getGreeting ()}</div >}
When to use defaultReturn:
- ✅ When the callback is invoked immediately and facets might not be initialized yet
- ✅ To provide a sensible fallback value that matches the expected return type
- ✅ To avoid conditional logic checking for
NO_VALUEin the calling code
When not needed:
- ❌ When facets are always initialized before the callback can be invoked
- ❌ When you can handle
NO_VALUEappropriately in the calling code