Websites v4 docs v5.2.5
    Preparing search index...

    Accessing Data and State

    The method of accessing data depends on whether you're working in a server component or client component.

    Note

    If in doubt whether you need to create a server or client component, always start with a server component and add 'use client'; to convert it to a client component if/when you realise you need to add some interactivity.

    Every theme page should be wrapped in ThemePage, which will expose some of the most common data as props:

    // app/[domain]/page.tsx

    <ThemePage pageName={PageName.Home} theme="carina">
    {({ pageConfig, agency, globalConfig }) => {
    if (!pageConfig) notFound();

    return <Home pageConfig={pageConfig} agency={agency} globalConfig={globalConfig} />;
    }}
    </ThemePage>

    You can therefore pass these props to children to make use of this data.

    In some cases you will need to access data either not provided by ThemePage or in a disconnected part of the document. In these cases you can fetch the data yourself. Caching and request memoization should prevent the app making more requests than necessary even if you are fetching the same data in multiple different places on a page.

    // The component must be async to make requests
    default async function MyServerComponent() {
    // fetch the current agency and return an instance of the agency model
    const agency = await Agency.current()

    // fetch the current agency's GlobalConfig Mongo document
    const globalConfig = await GlobalConfig.findByAgency(agency);

    // fetch theme settings Mongo document - pass theme as a string and type to generic
    const themeSettingsConfig = await ThemeSettingsConfig.findOneBy<CarinaThemeSettings>({
    agencyId: agency.id,
    theme: 'carina',
    });

    // fetch the first 10 branches and return an array of branch model instances
    const { results: branches, errors } = await Branch.findAll({ pageSize: 10 });

    // fetch a property by ID
    const { result, errors } = await Property.findById(id);

    return null;
    }

    See the API reference for Models for more examples.

    Most client components in the app will have access to various state via hooks:

    'use client';

    import useAgency from '@homeflow/v4-lib/hooks/use-agency';
    import useThemeSettings from '@homeflow/v4-lib/hooks/use-theme-settings';
    import { CarinaThemeSettings } from '../../theme-settings';
    import useThemeSettings from '@homeflow/v4-lib/hooks/use-global-config';

    default function MyClientComponent() {
    // get the current agency as a serializable/simple JS object
    const agency = useAgency();

    // get the current agency's global config as a serializable/simple JS object
    const globalConfig = useGlobalConfig();

    // get the current agency's theme settings for this theme - pass theme settings type to generic
    const themeSettings = useThemeSettings<CarinaThemeSettings>();

    return null;
    }

    In many cases it's best to leverage streaming by fetching data in server components and passing that data to client components as props. However the data normally needs to be simplified (or made serializable) before it can be passed to a client component.

    The most efficient way to do this is to directly call toJSON() on the object. In the case of arrays you will need to use map() and call this on each item.

    // fetch a property by ID
    const { result, errors } = await Property.findById(id);

    // serialize and then deserialize it to convert it to a simple JS object
    const serializableProperty = result.toJSON();

    // then pass to client component
    return <MyClientComponent property={serializableProperty} />

    The structure of the serializable data for Models is defined in the relevant Serializer method. You may need to add additional fields to serializers when new accessors are added to models.

    Note

    Another way of converting complex objects to serializable ones is to serialize and then deserialize them using JSON.parse(JSON.stringify(result)). Although this is more convenient and predictable (particularly with nested objects) it's slightly less performant than calling toJSON() directly.