<!-- Source: https://docs.squirro.com/en/latest/technical/widgets/react/hooks.html -->
# Available React Hooks

This page describes the React hooks available for use.

> **Note**
>
> The following React hooks are available under the `Hooks` object, for example `Hooks.useCollection`.

## useCollection

`useCollection(collection, isEmpty, serializer, additionalDeps)`

This hook attaches a Backbone collection to a React state and returns a serialized collection object together with loading and `isError` collection states.

Arguments:

1. **Collection** - Backbone collection object
2. **isEmpty** - Custom function that will determine if the collection is empty. Most of the time you can just check if `collection.length === 0`, but sometimes you may need to do additional things depending on the use case.
3. **Serializer** - Optional serializer function. If it’s not passed collection will be serialized with `collection.toJSON()`
4. **additionalDeps** - Additional `useEffect` dependencies that will trigger collection refetch on change. By default, the only dependency is the dashboard state object, but you can pass additional ones if needed.

## useCollectionRecreate

`useCollectionRecreate = (getCollection, props, config)`

This hook recreates a collection based on a change in the parameters.

Arguments:

1. **GetCollection**: Function to get a collection with parameters.
2. **WidgetProps**: An object representing widget properties to be passed down.
3. **Config**: An object representing widget config to be passed down.

## useWidgetCollection

`useWidgetCollection(widgetProps, collection, isEmpty, serializer, additionalDeps)`

This hook attaches a Backbone collection to a React state and returns an object with all properties needed for a widget. You can use this hook when setting up the main collection for the widget.

It uses the `useCollection` hook but also adds additional data and structure that helps with passing properties to widget containers and the widgets themselves.

Arguments:

1. **widgetProps** - An object representing widget properties to be passed down.
2. **Collection**: Backbone collection object
3. **isEmpty**: Custom function determining if the collection is empty. Mostly, you can check if `collection.length === 0`, though sometimes additional configuration is needed depending on the use case.
4. **Serializer**: Optional serializer function. If not passed, then collection will be serialized with `collection.toJSON()`
5. **additionalDeps**: Additional `useEffect` dependencies that trigger collection refetch on change. By default, the only dependency is the dashboard state object, though you can pass additional ones if needed.

## useCommunityTypesCollection

`useCommunityTypesCollection = (props, collection, isEmpty, dashboardSection, serializer)`

This hook calls the `useWidgetCollection` hook and provides a list of additional methods and parameters specific to `CommunityTypesCollection`.

Additional return parameters:

1. **GetModelById**: Function to get a CommunityType by ID.
2. **Total**: Number of Community Types.

Arguments:

1. **WidgetProps**: An object representing widget properties to be passed down.
2. **Collection**: Backbone collection object.
3. **isEmpty**: Custom function determining if the collection is empty. Mostly, you can check if `collection.length === 0`, though sometimes additional configuration is needed depending on the use case.
4. **DashboardSection**: The widget section in the Dashboard.
5. **Serializer**: Optional serializer function. If not passed, then collection will be serialized with `collection.toJSON()`.

## useCommunityCollection

`useCommunityCollection = (props, collection, isEmpty, dashboardSection, serializer, additionalDeps)`

This hook calls the `useWidgetCollection` hook and provides a list of additional methods and parameters specific to `CommunityCollection`.

Additional return parameters:

1. **GetModelById**: Function to get a Community by ID.
2. **Total**: Number of Communities.
3. **LoadNextPage**: Function to load the Collection next page (pagination).

Arguments:

1. **WidgetProps**: An object representing widget properties to be passed down.
2. **Collection**: Backbone collection object
3. **isEmpty**: Custom function determining if the collection is empty. Mostly, you can check if `collection.length === 0`, though sometimes additional configuration is needed depending on the use case.
4. **DashboardSection**: The widget section in the Dashboard.
5. **Serializer**: Optional serializer function. If not passed, then collection will be serialized with `collection.toJSON()`.
6. **AdditionalDeps**: Additional `useEffect` dependencies that trigger collection refetch on change. By default, the only dependency is the dashboard state object, though you can pass additional ones if needed.

## useCommunitySubscriptionsCollection

`useCommunitySubscriptionsCollection = (props, collection, isEmpty, dashboardSection, serializer)`

This hook calls the `useWidgetCollection` hook and provides a list of additional methods and parameters specific to `CommunitySubscriptionsCollection`.

Additional return parameters:

1. **GetModelById**: Function to get a CommunitySubscription by ID.
2. **Total**: Number of CommunitySubscriptions.
3. **LoadNextPage**: Function to load the Collection next page (pagination).
4. **Create**: Function to create a new CommunitySubscription.
5. **RefetchCollection**: Function to refetch the Collection.
6. **BulkCreate**: Function to create multiple CommunitySubscriptions.

Arguments:

1. **WidgetProps** - An object representing widget properties to be passed down.
2. **Collection** - Backbone collection object
3. **isEmpty** - Custom function determining if the collection is empty. Mostly, you can check if `collection.length === 0`, though sometimes additional configuration is needed depending on the use case.
4. **DashboardSection** - The widget section in the Dashboard
5. **Serializer** - Optional serializer function. If not passed, then collection will be serialized with collection.toJSON()

## useContainerDimensions

`useContainerDimensions(ref)`

This hook will return the width and the height of an HTML element.

Dimensions are updated on load, on mount/un-mount, when resizing the window, and when the ref changes.

Argument:

**Ref**: React ref object representing html element. For more information, see the [Refs and the DOM](https://reactjs.org/docs/refs-and-the-dom.html) reference page.

Example:

```
const elementRef = React.useRef(null);
const { containerWidth, containerHeight } = useContainerDimensions(carouselRef);
return <SomeComponent ref={elementRef}>
```

## useDashboardState

`useDashboardState(options)`

This hook provides a clean, typed API for interacting with the dashboard state store. It is the primary method for managing dashboard selections, queries, facets, time filters, and other dashboard-level state in widgets.

The dashboard state uses Zustand for state management which provides a modern, performant solution for managing complex dashboard interactions.

### Arguments

The hook accepts a single options object with the following properties:

1. **dashboard**: Dashboard model available in widget props
2. **dashboardState**: Dashboard state instance (Zustand store) available in widget props as well, or can be any custom `dashboardState` store
3. **widgetModel**: Widget configuration model available in widget props

Example:

```javascript
const selectionsStore = useDashboardState({
    dashboard: props.dashboard,
    dashboardState: props.dashboardState,
    widgetModel: props.widgetModel,
});
```

### Return Value

The hook returns an object with the following properties and methods:

#### State Properties

- **selections**: `IDashboardSelection[]` - Array of current dashboard selections
- **selectionsQuery**: `string` - Cached query string built from selections
- **globalSearchMode**: `'all' | 'context'` - Current search mode
- **id**: `string` - Unique identifier for this dashboard state instance
- **instance**: `IDashboardState` - Raw Zustand store instance for advanced use
- **lastSearchQuery**: `string` - The last executed search query string
- **widgetId**: `string` - Unique identifier for the current widget
- **isEmpty**: `() => boolean` - Function that returns true if there are no active selections
- **isTimeRestricted**: `() => boolean` - Function that returns true if time filters are applied

### Methods

#### Selection Management

##### addFacets

`addFacets(facets: [string, string][])`

Adds one or more facet-value pairs as dashboard selections.

Arguments:

1. **facets**: Array of [facet, value] tuples

Example:

```javascript
const store = useDashboardState({ dashboard, dashboardState, widgetModel });

// Add single facet
store.addFacets([['source', 'news']]);

// Add multiple facets
store.addFacets([
    ['category', 'technology'],
    ['author', 'John Smith']
]);
```

##### addSelections

`addSelections(selections: Omit<IDashboardSelection, 'id'>[])`

Adds custom selections to the dashboard state. This is useful for adding selections with specific properties like icons, colors, or custom query formats.

Arguments:

1. **selections**: Array of selection objects (without id, which is auto-generated)

Example:

```javascript
store.addSelections([
    {
        query: 'title:AI',
        type: 'FIELD',
        widgetId: widgetModel.id,
        name: 'AI Topics',
        icon: 'search'
    }
]);
```

##### removeSelections

`removeSelections(selections: IDashboardSelection[])`

Removes specific selections from the dashboard state.

Arguments:

1. **selections**: Array of selection objects to remove

Example:

```javascript
// Remove specific selection
const selectionToRemove = store.selections.find(s => s.query === 'test');
if (selectionToRemove) {
    store.removeSelections([selectionToRemove]);
}
```

##### setSelections

`setSelections(selections: IDashboardSelection[] | (state) => IDashboardSelection[], selectionsToRemove?: IDashboardSelection[])`

Replaces all selections with a new set. Can accept either an array or a function that receives current state. Optionally removes specific selections first.

Arguments:

1. **selections**: New selections array or updater function
2. **selectionsToRemove**: (Optional) Selections to remove before setting new ones

Example:

```javascript
// Replace all selections
store.setSelections([
    {
        id: '1',
        query: 'category:news',
        type: 'FIELD',
        widgetId: widgetModel.id
    }
]);

// Use updater function
store.setSelections((currentSelections) =>
    currentSelections.filter(s => s.type !== 'TERM')
);

// Remove specific selections then set new ones
store.setSelections(newSelections, oldSelectionsToRemove);
```

##### updateSelections

`updateSelections(selectionsToAdd: IDashboardSelection[], selectionsToRemove?: IDashboardSelection[])`

Updates selections by adding and/or removing in a single operation.

Arguments:

1. **selectionsToAdd**: Selections to add
2. **selectionsToRemove**: (Optional) Selections to remove

Example:

```javascript
store.updateSelections(
    [{ query: 'new', type: 'TERM', widgetId: widgetModel.id }],
    oldSelections
);
```

##### reset

`reset(options?: { resetGlobalSearch?: boolean })`

Resets the dashboard state to its initial state, clearing all selections.

Arguments:

1. **options**: (Optional) Configuration object with `resetGlobalSearch` boolean - Whether to also reset global search state

Example:

```javascript
// Reset all selections
store.reset();

// Reset including global search
store.reset({ resetGlobalSearch: true });
```

#### Query Operations

##### addQuerySelection

`addQuerySelection(query: string, options?: { clear?: boolean })`

Adds a query string as a dashboard selection. The query is parsed into tokens and converted to selection chips.

Arguments:

1. **query**: Query string to add
2. **options**: (Optional) Object with `clear` flag to replace existing query

Example:

```javascript
// Add to existing query
store.addQuerySelection('artificial intelligence');

// Replace entire query
store.addQuerySelection('machine learning', { clear: true });
```

##### getQuery

`getQuery(options?: IGetSearchParamsOptions): string`

Returns the combined query string from all selections, dashboard and widget queries.

Arguments:

1. **options**: (Optional) Configuration object:
   - `ignoreGlobalSearch`: boolean - Ignore global search mode
   - `includeDisabled`: boolean - Include disabled selections
   - Other options from IGetSearchParamsOptions

Example:

```javascript
const query = store.getQuery();
const queryWithoutGlobal = store.getQuery({ ignoreGlobalSearch: true });
```

##### getSearchParams

`getSearchParams<ContextType>(options?): IApiParams<ContextType>`

Returns formatted parameters ready for API calls, including query, facets, time range, etc.

Arguments:

1. **options**: (Optional) Same as getQuery options

Example:

```javascript
const params = store.getSearchParams();
// Returns: { query: '...', query_context: { searchbar_query: '...', dashboard_filters: {...}, ... }, created_after: '...', ... }
```

##### getQueryId

`getQueryId(): number`

Returns a unique ID for the current query state, useful for cache invalidation.

Example:

```javascript
const queryId = store.getQueryId();
// Use as cache key
```

##### getQueryGlobalSearch

`getQueryGlobalSearch(): string`

Returns the global search query string.

##### getAdditionalQuery

`getAdditionalQuery(): () => string`

Returns a function that retrieves the additional query configuration for the current widget.

Example:

```javascript
const getAdditionalQuery = store.getAdditionalQuery();
const additionalQuery = getAdditionalQuery();
```

##### getConcept

`getConcept(): string | null`

Returns the current concept selection.

Example:

```javascript
const concept = store.getConcept();
if (concept) {
    console.log('Current concept:', concept);
}
```

##### getFacets

`getFacets(): IFacet[]`

Returns an array of all facets extracted from the current selections.

Example:

```javascript
const facets = store.getFacets();
// Returns: [{ name: 'category', value: 'news' }, ...]
```

##### getLastSearchQuery

`getLastSearchQuery(): string`

Returns the last search query string that was executed.

Example:

```javascript
const lastQuery = store.getLastSearchQuery();
```

##### changeGlobalSearchMode

`changeGlobalSearchMode(mode: 'all' | 'context')`

Changes the global search mode between ‘all’ (search all content) and ‘context’ (search within current context).

Arguments:

1. **mode**: Search mode - either ‘all’ or ‘context’

Example:

```javascript
// Switch to context-aware search
store.changeGlobalSearchMode('context');

// Switch to search all
store.changeGlobalSearchMode('all');
```

#### Widget-Specific Operations

##### updateWidgetSelection

`updateWidgetSelection(selectionsToAdd?, selectionsToRemove?, options?)`

Updates selections specific to the current widget. Automatically filters by widget ID.

Arguments:

1. **selectionsToAdd**: (Optional) Selections to add for this widget
2. **selectionsToRemove**: (Optional) Selections to remove for this widget
3. **options**: (Optional) Configuration object:
   - `clearOtherSelections`: boolean - Clear all other selections from this widget before adding new ones
   - `widgetId`: string - Override the widget ID (defaults to current widget)

Example:

```javascript
// Replace widget's selections
store.updateWidgetSelection(
    newSelections,
    null,
    { clearOtherSelections: true }
);

// Update another widget's selections
store.updateWidgetSelection(
    newSelections,
    oldSelections,
    { widgetId: 'other-widget-id' }
);
```

##### clearWidgetSelection

`clearWidgetSelection(options?: { widgetId?: string })`

Clears all selections created by the current (or specified) widget.

Arguments:

1. **options**: (Optional) Object with `widgetId` to clear different widget’s selections

Example:

```javascript
// Clear current widget's selections
store.clearWidgetSelection();

// Clear specific widget's selections
store.clearWidgetSelection({ widgetId: 'other-widget-id' });
```

##### getWidgetSelection

`getWidgetSelection(options?): IDashboardSelection[]`

Returns selections created by the current (or specified) widget.

Arguments:

1. **options**: (Optional) Configuration object:
   - `widgetId`: string - Get selections from different widget (defaults to current widget)
   - `filterTypes`: array of selection types - Filter results to only specific types (e.g., [‘FIELD’, ‘TERM’])

Example:

```javascript
// Get all selections from current widget
const mySelections = store.getWidgetSelection();

// Get selections from another widget
const otherSelections = store.getWidgetSelection({ widgetId: 'other-widget-id' });

// Get only FIELD type selections from current widget
const fieldSelections = store.getWidgetSelection({ filterTypes: ['FIELD'] });

// Combine filters
const filteredSelections = store.getWidgetSelection({
    widgetId: 'other-widget-id',
    filterTypes: ['FIELD', 'TERM']
});
```

#### Specialized Setters

##### setConcept

`setConcept(concept: string | null)`

Sets or clears the concept selection.

Arguments:

1. **concept**: Concept string or null to clear

Example:

```javascript
store.setConcept('technology');
store.setConcept(null); // Clear concept
```

##### setTime

`setTime(start?, end?, options?)`

Sets the time range filter.

Arguments:

1. **start**: Start date/time
2. **end**: End date/time
3. **options**: (Optional) Configuration object

Example:

```javascript
store.setTime('2024-01-01', '2024-12-31');
store.setTime(null, null); // Clear time filter
```

##### setSort

`setSort(field, order, options)`

Sets the sort field and order.

Arguments:

1. **field**: Field name to sort by
2. **order**: Sort order (‘asc’ or ‘desc’)
3. **options**: Configuration object

Example:

```javascript
store.setSort('created_at', 'desc', {});
```

##### getTime

`getTime(key: 'start' | 'end')`

Gets the start or end time from the current time selection.

Arguments:

1. **key**: Either ‘start’ or ‘end’

Example:

```javascript
const startTime = store.getTime('start');
const endTime = store.getTime('end');
```

##### setLastSearchQuery

`setLastSearchQuery(query: string)`

Sets the last search query string. This is used to track the most recent query to not search for the same queries.

Arguments:

1. **query**: The query string to store

Example:

```javascript
store.setLastSearchQuery('artificial intelligence');
```

#### Community Management

##### setSelectedCommunity

`setSelectedCommunity(community: ICommunity | null)`

Sets or clears the selected community.

Arguments:

1. **community**: Community object or null to clear

Example:

```javascript
store.setSelectedCommunity(communityObj);
store.setSelectedCommunity(null); // Clear
```

##### getSelectedCommunityQuery

`getSelectedCommunityQuery(): string`

Returns the query string for the selected community.

Example:

```javascript
const communityQuery = store.getSelectedCommunityQuery();
```

##### getSelections

`getSelections(): IDashboardSelection[]`

Returns all current dashboard selections as an array.

Example:

```javascript
const allSelections = store.getSelections();
console.log('Total selections:', allSelections.length);

// Iterate through selections
allSelections.forEach(selection => {
    console.log('Selection:', selection.query, selection.type);
});
```

#### State Subscriptions

##### subscribe

`subscribe(selector, callback, options)`

Subscribes to specific state changes using a selector function.

Arguments:

1. **selector**: Function to select state slice
2. **callback**: Function called when selected state changes
3. **options**: (Optional) Subscription options

Example:

```javascript
useEffect(() => {
    // Subscribe to selection changes
    const unsubscribe = store.subscribe(
        (state) => state.selections, // or any state value, like state.timeSelection or state.globalSearchMode
        (value) => { // argument would be a value for which you've subscribed
            console.log('State value changed:', value);
        }
    );

    return unsubscribe;
}, []);
```

### Complete Usage Example

Here’s a complete example showing common dashboard state operations in a widget:

```jsx
const MyWidget = (props) => {
    const store = Hooks.useDashboardState({
        dashboard: props.dashboard,
        dashboardState: props.dashboardState,
        widgetModel: props.widgetModel,
    });

    // Handle facet click
    const handleFacetClick = (facet, value) => {
        store.addFacets([[facet, value]]);
    };

    // Handle search
    const handleSearch = (searchText) => {
        store.addQuerySelection(searchText);
        // Track last search
        store.setLastSearchQuery(searchText);
    };

    // Clear all filters
    const handleClearAll = () => {
        store.reset();
    };

    // Clear widget's filters
    const handleClear = () => {
        store.clearWidgetSelection();
    };

    // Toggle global search mode
    const handleToggleSearchMode = () => {
        const newMode = store.globalSearchMode === 'all' ? 'context' : 'all';
        store.changeGlobalSearchMode(newMode);
    };

    // Subscribe to selection changes
    React.useEffect(() => {
        const unsubscribe = store.subscribe(
            (state) => state.selections,
            (newSelections) => {
                console.log('Dashboard selections updated:', newSelections);
                console.log('Is empty?', store.isEmpty());
                console.log('Has facets?', store.getFacets().length > 0);
                // Refresh widget data
            }
        );

        return unsubscribe;
    }, []);

    return (
        <div>
            <button onClick={() => handleFacetClick('category', 'news')}>
                Filter by News
            </button>
            <button onClick={() => handleSearch('artificial intelligence')}>
                Search AI
            </button>
            <button onClick={handleClear}>
                Clear Widget Filters
            </button>
            <button onClick={handleClearAll}>
                Clear All Filters
            </button>
            <button onClick={handleToggleSearchMode}>
                Toggle Search Mode ({store.globalSearchMode})
            </button>
            <div>
                <div>Current selections: {store.selections.length}</div>
                <div>Is empty: {store.isEmpty()}</div>
                <div>Widget ID: {store.widgetId}</div>
                <div>Last query: {store.lastSearchQuery || 'none'}</div>
            </div>
        </div>
    );
};
```

### Troubleshooting

**Issue**: Selections not updating in UI

**Solution**: Ensure that you’re using the `props.dashboardState` or `Globals.dashboardState` when updating selections. Other dashboard widgets are only listening to that state changes.

```javascript
const store = Hooks.useDashboardState({
    dashboard: props.dashboard,
    dashboardState: props.dashboardState,
    widgetModel: props.widgetModel,
});

// Handle search
const handleSearch = (searchText) => {
    store.addQuerySelection(searchText);
};
```

**Issue**: Facets not being removed correctly

**Solution**: Make sure you’re passing the full selection object that matches selection’s query or ID, not just facet/value:

```javascript
// Find the selection first
const selection = store.selections.find(s => s.query === targetQuery);
store.removeSelections([selection]);
```

**Issue**: Widget selections conflicting with dashboard

**Solution**: Use widget-specific methods:

```javascript
// Clear only this widget's selections
store.clearWidgetSelection();

// Get only this widget's selections
const mySelections = store.getWidgetSelection();

// Update current widget selection
store.updateWidgetSelection(newSelections, oldSelections);
```

### Additional Resources

The best documentation is the implementation. If you have any doubts, check the types and actual implementation, which can be found in the following places:

- **Storybook**: Interactive examples of dashboard state usage: [https://storybook.squirro.com](https://storybook.squirro.com)
- **Dashboard State Store Implementation**: `integration/frontend/userapp/static/js/require/views/react/dashboardState.ts`
- **Hook Implementation**: `integration/frontend/userapp/static/js/require/views/react/hooks.ts`

## useFacetsCollection

`useFacetsCollection = (props, collection, isEmpty, dashboardSection, serializer)`

This hook calls the `useWidgetCollection` hook and provides a list of additional methods and parameters specific to `FacetsCollection`.

Additional return parameters:

1. **GetModelById**: Function to get a Facet by ID.
2. **Indexed**: List of Indexed Facets.

Arguments:

1. **WidgetProps**: An object representing widget properties to be passed down.
2. **Collection**: Backbone collection object.
3. **isEmpty**: Custom function determining if the collection is empty. Mostly, you can check if `collection.length === 0`, though sometimes additional configuration is needed depending on the use case.
4. **DashboardSection**: The widget section in the Dashboard.
5. **Serializer**: Optional serializer function. If not passed, then collection will be serialized with `collection.toJSON()`.

## useFeedbackMode

`useFeedbackMode = (dashboard)`

This hook tracks the `FeedbackMode` in a dashboard and returns the `boolean` representing the current mode and a `setFeedbackMode` function to change it.

Argument:

**Dashboard**: Dashboard model, available in all the widgets props.

## useItemsCollection

`useItemsCollection = (props, collection, overrides, apiOverrides, dashboardSection,additionalDeps, isEmpty, serializer)`

This hook calls the `useWidgetCollection` hook, attaches additional events, and provides a list of additional methods and parameters specific to `ItemsCollection`.

Additional return parameters:

1. **LoadNextPage**: Function to load the Collection next page (pagination).
2. **ActiveItem**: The current active Item.
3. **SetActiveItem**: Function to set the active Item.
4. **GetActiveItem**: Function to get the active Item.
5. **ActiveEntity**: The current active Entity.
6. **SetActiveEntity**: Function to set the active Entity.
7. **GetActiveEntity**: Function to get the active Entity.
8. **GetExcelUrl**: Function to get the Excel URL.
9. **GetModelById**: Function to get an Item by ID.
10. **OnEntityClick**: Function to be called when an Entity is clicked.

Arguments:

1. **WidgetProps**: An object representing widget properties to be passed down.
2. **Collection**: Backbone collection object.
3. **Overrides**: Object containing all the Widget Component Overrides.
4. **ApiOverrides**: Object containing all the Widget API Overrides.
5. **DashboardSection**: The widget section in the Dashboard.
6. **isEmpty**: Custom function determining if the collection is empty. Mostly, you can check if `collection.length === 0`, though sometimes additional configuration is needed depending on the use case.
7. **Serializer**: Optional serializer function. If not passed, then collection will be serialized with `collection.toJSON()`.
8. **AdditionalDeps** - Additional `useEffect` dependencies that trigger collection refetch on change. By default, the only dependency is the dashboard state object, though you can pass additional ones if needed.

## useQueryEvaluator

`useQueryEvaluator = (additionalQuery, dashboard, user, search)`

This hook evaluates the query and attaches events to the Dashboard Store and returns it as a string.

Arguments:
1. **AdditionalQuery**: Additional widget query as a string.
2. **Dashboard**: Dashboard model available in all the widget props.
3. **User**: User model.
4. **Search**: Search model, available in all the widget props.

## useStoreKeyChange

`useStoreKeyChange = (dashboard, storeKey, event)`

This hook tracks a store key based on a given event and returns the value.

Arguments:

1. **Dashboard**: Dashboard model, available in all the widgets props.
2. **StoreKey**: A string representing the store key.
3. **Event**: A string representing the event.

## useStateWithCallback

`useStateWithCallback = (initialValue)`

This hook saves a state value and returns the current value and a function to update the value and use a specified callback function.

Argument:

**InitialValue**: The initial value of the state, can be of `any` type.

Example:

```javascript
const [value, setValueAndCallback] = useStateWithCallback('firstValue');
setValueAndCallback('secondValue', (prevValue, newValue) => console.log(`Previous value: ${prevValue}, New value: ${newValue}`));
```

## useWithoutCollection

`useWithoutCollection = (widgetProps)`

This hook acts similarly to `useCollection` but it doesn’t use a collection. It can be used for widgets without specified collections.

Argument:

**WidgetProps**: An object representing widget properties to be passed down.

## usePrevious

`usePrevious = (value)`

This hook tracks the previous value of a given one and returns it.

Argument:

**Value**: Mutating value of any kind.
