useResource
useResource is the primary way to fetch data with Atomic React.
It returns a Resource object, that is still loading when initially returned.
When the data is loaded, the component will re-render with the new data allowing you to show some UI before the content is available, resulting in a more responsive user experience.
The hook also subscribes to changes meaning that the component will update whenever the data changes clientside and even serverside. You essentially get real-time features for free!
import { useResource } from '@tomic/react';
export const Component = () => {
const resource = useResource('https://my-atomic-server/my-resource');
// Show an error message if the resource has an error
if (resource.error) {
return <ErrorCard error={resource.error} />
}
// Optionally show a loading state
if (resource.loading) {
return <Loader />
}
return (
<p>{resource.title}</p>
)
}
Typescript
Just like the store.getResource method, useResource can be annotated with a subject of a certain class.
import { useResource } from '@tomic/react';
import type { Author } from './ontologies/blogsite' // <-- Generated with @tomic/cli
// ...
const resource = useResource<Author>('https://my-atomic-server/moderndayshakespear69')
const age = Date.now() - resource.props.yearOfBirth
Reference
Parameters
- subject:
string- The subject of the resource you want to fetch. - options:
UseResourceOptions- (Optional) Options for how the store should fetch or update the resource.
UseResourceOptions:
| Name | Type | Description |
|---|---|---|
| noWebSocket | boolean | (Optional) If true, uses HTTP to fetch resources instead of websockets |
| newResource | Resource | (Optional) If true, will not send a request to a server, it will simply create a new local resource. |
| track | string[] | (Optional) By default useResource will update the reference of the resource whenever any property changes, both local and remote changes. Sometimes you want to only update the resource when certain properties change, you can use this option to specify which properties to track. Remote changes will still trigger a rerender. |
Returns
Resource - The fetched resource (might still be in a loading state).
Views
A common way to build interfaces with Atomic React is to make a view component. Views are a concept where the component is responsible for rendering a resource in a certain way to fit in the context of the view type.
The view selects a component based on the resource’s class or renders a default view when there is no component for that class.
In this example, we have a ResourceInline view that renders a resource inline in some text.
For most resources, it will just render the name but for a Person or Product, it will render a special component.
// views/inline/ResourceInline.tsx
import { useResource } from '@tomic/react';
import { shop } from '../../ontologies/shop'; // <-- Generated with @tomic/cli
import { PersonInline } from './PersonInline';
import { ProductInline } from './ProductInline';
interface ResourceInlineProps {
subject: string;
}
export interface ResourceInlineViewProps<T> {
resource: Resource<T>;
}
export const ResourceInline = ({ subject }: ResourceInlineProps): JSX.Element => {
const resource = useResource(subject);
const Comp = resource.matchClass({
[shop.classes.product]: ProductInline,
[shop.classes.person]: PersonInline,
}, Default);
return <Comp subject={subject} />
}
const Default = ({ resource }: ResourceInlineViewProps<unknown>) => {
return <span>{resource.title}</span>
}
The PersonInline view will render a person resource inline.
It could render a mention-like thing with the person’s name, their profile picture and a link to their profile for example.
// views/inline/PersonInline.tsx
import { useResource, Resource, type Server } from '@tomic/react';
import type { Person } from '../../ontologies/social' // <-- Generated with @tomic/cli
import type { ResourceInlineViewProps } from './ResourceInline';
export const PersonInline = ({ resource }: ResourceInlineViewProps<Person>) => {
// Get the person's profile picture resource with the useResource hook
const image = useResource<Server.File>(resource.props.image);
return (
<span className="person-inline">
<img src={image.props.downloadUrl} className="profile-image-inline" />
<span>{resource.title}</span>
</span>
)
}