Hey there. I am developing a custom component library for Retool using TypeScript. If there is a way to add data type to Retool.useStateObject
hook?
For example I have a data contract like this:
interface IListItem {
id: number;
name: string;
description: string;
}
How can I expose an object state value to Retool using this type with Retool.useStateObject<IListItem>()
, or is there a preferred way to do this in the current API?
Hey @MChuduk, welcome to the Retool Community!
I recommend checking out the Retool Custom Component documentation β a great resource.
1 Like
Hey, tanks for reply. I checked the documentation as well, but I can't realize why Retool.useStateObject
is not a generic for some reason.
I used a workaround to solve this problem, but I'm not sure that's better way to do that:
const [item] = Retool.useStateObject({
name: 'item'
}) as unknown as [IlistItem, (value: IlistItem) => void]
Hey @MChuduk ,
You might consider using the following approach to expose an object state value:
const [state, setState] = Retool.useStateObject<IListItem>({
name: 'listItem',
initialValue: { id: 0, name: '', description: '' },
inspector: 'text',
description: 'A list item state',
label: 'List Item',
});
1 Like
Maybe I'm confusing something. But Retool.useStateObject
is not a generic function according to definition:
function useStateObject({
name,
initialValue,
inspector,
description,
label,
}: {
name: string
initialValue?: SerializableObject
inspector?: 'text' | 'hidden'
description?: string
label?: string
}): readonly [SerializableObject, (newValue: SerializableObject) => void]
It means that I can't provide an object type using <>
brackets.
Hey @MChuduk
Apologies for the confusion earlier β that was my oversight in not fully understanding the issue.
The Retool SDK doesnβt support generics directly with useStateObject
. However, we can safely cast the result as a tuple with the appropriate types, as shown below:
import { type FC, useEffect } from 'react'
import { Retool } from '@tryretool/custom-component-support'
interface IListItem {
id: number
name: string
description: string
}
export const DemoStateObject: FC = () => {
const [item, setItem] = Retool.useStateObject({ name: 'selectedItem' }) as [
IListItem,
(val: IListItem) => void
]
useEffect(() => {
console.log('Selected item from Retool:', item)
// Optional: set a new object to sync back to Retool
setItem({
id: 1,
name: 'Sample Item',
description: 'This is a sample description'
})
}, [])
return (
<div>
<h1>{item?.id}</h1>
<h2>{item?.name}</h2>
<p>{item?.description}</p>
</div>
)
}
In Retool, create a temporary state variable called selectedItem
and initialize it with an object like this:
{
"id": 101,
"name": "Test Item",
"description": "Test description here"
}
2 Likes
Well, there is only one way how to handle it at the moment. Thanks for suggestion.