Model properties
Hooks to list, load, add and remove the property definitions of a model, for schema editors.
A model property is a field definition on a model, such as title: Text on Post. These hooks return ModelProperty instances from @seedprotocol/sdk. They describe fields; they don't hold item values. For the values stored on an item, see Item properties.
import {
useModelProperties,
useModelProperty,
useCreateModelProperty,
useDestroyModelProperty,
} from '@seedprotocol/react'The read hooks wait for the client to be ready before they query. While mounted, each one holds the properties it shows, and when a shown property stops (destroyed, or removed with its model or schema) the hook looks it up again. useModelProperties caches through React Query: outside SeedProvider it uses a shared fallback client with Seed's defaults, and development builds log a warning, so keep it inside SeedProvider (which hooks need it). The ModelProperty class is covered in ModelProperty.
useModelProperties
Lists the property definitions of one model, and updates when properties are added or removed.
function useModelProperties(
schemaIdOrModelId: string | null | undefined,
modelName?: string | null | undefined,
): {
modelProperties: ModelProperty[]
isLoading: boolean
error: Error | null
}Parameters
| Name | Type | Description |
|---|---|---|
schemaIdOrModelId | string | null | undefined | With modelName: the schema name or schema file ID. Without it: the model's file ID |
modelName | string | null | undefined | The model's name. Leave it out to look up by model file ID |
The model is resolved with useModel, so the same two forms apply.
Returns
| Field | Type | Description |
|---|---|---|
modelProperties | ModelProperty[] | The model's properties. [] until loaded |
isLoading | boolean | true only while the list is empty and loading. Background refetches don't set it |
error | Error | null | The query's error, if ModelProperty.all() failed |
If the first load finds no properties (they can be written a moment after the model), the hook retries after 400 ms, 1.2 s and 2.5 s.
Example
import { useModelProperties } from '@seedprotocol/react'
export function PostFields() {
const { modelProperties, isLoading, error } = useModelProperties('blog', 'Post')
if (isLoading) return <p>Loading fields…</p>
if (error) return <p>{error.message}</p>
return (
<table>
<tbody>
{modelProperties.map((property) => (
<tr key={property.name}>
<td>{property.name}</td>
<td>{property.dataType}</td>
</tr>
))}
</tbody>
</table>
)
}useModelProperty
Loads one property definition. It has three call forms.
function useModelProperty(propertyFileId: string | null | undefined): Result
function useModelProperty(
modelFileId: string | null | undefined,
propertyName: string | null | undefined,
): Result
function useModelProperty(
schemaId: string | null | undefined,
modelName: string | null | undefined,
propertyName: string | null | undefined,
): Result
type Result = {
modelProperty: ModelProperty | undefined
isLoading: boolean
error: Error | null
}Parameters
| Form | Arguments | Looks up |
|---|---|---|
| One argument | propertyFileId | The property by its file ID |
| Two arguments | modelFileId, propertyName | The named property on the model with that file ID |
| Three arguments | schemaId, modelName, propertyName | The named property on that model, in the schema with that name |
The number of arguments picks the form. While any of them is null or undefined, the hook loads nothing and returns modelProperty: undefined with isLoading: false, so useModelProperty(schemaId, selectedModel, selectedProperty) waits until a model and a property are selected.
Returns
| Field | Type | Description |
|---|---|---|
modelProperty | ModelProperty | undefined | The property, or undefined if not found or not loaded |
isLoading | boolean | true while the lookup runs |
error | Error | null | The lookup error, if any |
Only the one-argument form subscribes to the property: it reloads (debounced by 100 ms) whenever the property's state changes. The two- and three-argument forms look the property up once, retry after 400 ms, 1.2 s and 2.5 s while nothing is found, and then update only when the property stops. Use the one-argument form, or useModelProperties, in an editor where the definition can change.
Example
import { useModelProperty } from '@seedprotocol/react'
export function TitleType() {
const { modelProperty } = useModelProperty('blog', 'Post', 'title')
return <span>{modelProperty?.dataType}</span>
}
export function PropertyName({ propertyFileId }: { propertyFileId: string }) {
const { modelProperty, isLoading, error } = useModelProperty(propertyFileId)
if (error) return <p>{error.message}</p>
return <span>{isLoading ? '…' : modelProperty?.name}</span>
}In the three-argument form, schemaId has to be the exact name or schema file ID of a stored schema. When none matches (a typo, or a schema that isn't stored yet), modelProperty is undefined. useCreateModelProperty resolves schemaId the same way.
useCreateModelProperty
Adds a property definition to a model and tracks its progress.
function useCreateModelProperty(): UseCreateModelPropertyReturn
type UseCreateModelPropertyReturn = {
create: (
schemaId: string,
modelName: string,
property: UseCreateModelPropertyOptions,
) => Promise<ModelProperty>
isLoading: boolean
error: Error | null
resetError: () => void
}
type UseCreateModelPropertyOptions = {
name: string
dataType: string
[key: string]: any
}Parameters of create
| Name | Type | Description |
|---|---|---|
schemaId | string | The exact name or schema file ID of a stored schema, as in useModelProperty |
modelName | string | The model to add the property to |
property | UseCreateModelPropertyOptions | The definition in the code shape: name, dataType (such as 'Text' or 'Relation'), and any of ref, refValueType, required, validation and the storage fields. name and dataType are required. The property definition reference describes each field |
Returns
| Field | Type | Description |
|---|---|---|
create | function | Resolves to the property's instance once the schema name is looked up. The instance can still be loading. Rejects (and sets error) if modelName, property.name or property.dataType is missing, with No stored schema has the name or schema file id "<schemaId>" when no stored schema matches, or with ClientNotInitializedError (code 'CLIENT_NOT_INITIALIZED') before the client's database is open. Call it once the client is ready |
isLoading | boolean | true from the call until the property's status is 'ready' or 'error', or create rejects. A property that's already loaded clears it at once |
error | Error | null | The rejection above, or, when the property's load fails, the load's own error (Failed to create model property if it isn't an Error) |
resetError | () => void | Clears error |
Example
import { useCreateModelProperty } from '@seedprotocol/react'
export function AddSummaryField() {
const { create, isLoading, error } = useCreateModelProperty()
return (
<>
<button
disabled={isLoading}
onClick={() => create('blog', 'Post', { name: 'summary', dataType: 'Text' }).catch(() => {})}
>
Add summary
</button>
{error && <p>{error.message}</p>}
</>
)
}useModelProperties('blog', 'Post') picks up the new property once it's written.
create calls ModelProperty.create without waiting for the property to load, and takes no hold, so there's nothing to unload(). If the model already has a property with that name, you get the existing instance back. If the model isn't in the local database, nothing is written: the promise still resolves with the instance, its status turns 'error', and error is set to Failed to create model property.
useDestroyModelProperty
Removes a property definition from its model.
function useDestroyModelProperty(): UseDestroyModelPropertyReturn
type UseDestroyModelPropertyReturn = {
destroy: (modelProperty: ModelProperty) => Promise<void>
isLoading: boolean
error: Error | null
resetError: () => void
}Returns
| Field | Type | Description |
|---|---|---|
destroy | (modelProperty: ModelProperty) => Promise<void> | Calls modelProperty.destroy(). Does nothing if the argument is falsy |
isLoading | boolean | true while destroy runs |
error | Error | null | Set if destroy() rejects |
resetError | () => void | Clears error |
destroy sets error and rejects when modelProperty.destroy() fails, database failures included. Catch the promise. useModelProperties drops the property from its list on its own. Items' stored values for the property are kept; see Other methods.
import type { ModelProperty } from '@seedprotocol/sdk'
import { useDestroyModelProperty } from '@seedprotocol/react'
export function RemoveField({ property }: { property: ModelProperty }) {
const { destroy, isLoading, error } = useDestroyModelProperty()
return (
<>
<button disabled={isLoading} onClick={() => destroy(property).catch(() => {})}>
Remove {property.name}
</button>
{error && <p>{error.message}</p>}
</>
)
}Related
- ModelProperty: the class these hooks return, and every definition field
- Models: hooks for the models that own these properties
- Item properties: hooks for the values stored on items
- Your first schema: property types in the schema file