UNPKG

tinybase

Version:

A reactive data store and sync engine.

1,382 lines (1,357 loc) 607 kB
/** * The ui-react module of the TinyBase project provides both hooks and * components to make it easy to create reactive apps with Store objects. * * The hooks in this module provide access to the data and structures exposed by * other modules in the project. As well as immediate access, they all register * listeners such that components using those hooks are selectively re-rendered * when data changes. * * The components in this module provide a further abstraction over those hooks * to ease the composition of user interfaces that use TinyBase. * @see Building UIs guides * @see Building UIs With Metrics guide * @see Building UIs With Indexes guide * @see Building UIs With Relationships guide * @see Building UIs With Queries guide * @see Building UIs With Checkpoints guide * @see Countries demo * @see Todo App demos * @see Drawing demo * @packageDocumentation * @module ui-react * @since v1.0.0 */ import type { CheckpointIds, CheckpointIdsListener, CheckpointListener, Checkpoints, } from '../checkpoints/index.d.ts'; import type { Callback, Id, IdOrNull, Ids, ParameterizedCallback, } from '../common/index.d.ts'; import type { Indexes, SliceIdsListener, SliceRowIdsListener, } from '../indexes/index.d.ts'; import type {MergeableStore} from '../mergeable-store/index.d.ts'; import type {MetricListener, Metrics} from '../metrics/index.d.ts'; import type { AnyPersister, PersistedStore, Persister, Persists, Status, StatusListener, } from '../persisters/index.d.ts'; import type { Queries, ResultCellIdsListener, ResultCellListener, ResultRowCountListener, ResultRowIdsListener, ResultRowListener, ResultSortedRowIdsListener, ResultTableCellIdsListener, ResultTableListener, } from '../queries/index.d.ts'; import type { LinkedRowIdsListener, LocalRowIdsListener, Relationships, RemoteRowIdListener, } from '../relationships/index.d.ts'; import type { Cell, CellIdsListener, CellListener, CellOrUndefined, HasCellListener, HasRowListener, HasTableCellListener, HasTableListener, HasTablesListener, HasValueListener, HasValuesListener, MapCell, MapValue, Row, RowCountListener, RowIdsListener, RowListener, SortedRowIdsListener, Store, Table, TableCellIdsListener, TableIdsListener, TableListener, Tables, TablesListener, TransactionListener, Value, ValueIdsListener, ValueListener, ValueOrUndefined, Values, ValuesListener, } from '../store/index.d.ts'; import type {Synchronizer} from '../synchronizers/index.d.ts'; import type {ComponentType, ReactElement} from 'react'; /** * The StoreOrStoreId type is used when you need to refer to a Store in a React * hook or component. * * In some simple cases you will already have a direct reference to the Store. * * This module also includes a Provider component that can be used to wrap * multiple Store objects into a context that can be used throughout the app. In * this case you will want to refer to a Store by its Id in that context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Store or its Id. * @category Identity * @since v1.0.0 */ export type StoreOrStoreId = Store | Id; /** * The MetricsOrMetricsId type is used when you need to refer to a Metrics * object in a React hook or component. * * In some simple cases you will already have a direct reference to the Metrics * object. * * This module also includes a Provider component that can be used to wrap * multiple Metrics objects into a context that can be used throughout the app. * In this case you will want to refer to a Metrics object by its Id in that * context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Metrics object or its * Id. * @category Identity * @since v1.0.0 */ export type MetricsOrMetricsId = Metrics | Id; /** * The IndexesOrIndexesId type is used when you need to refer to an Indexes * object in a React hook or component. * * In some simple cases you will already have a direct reference to the Indexes * object. * * This module also includes a Provider component that can be used to wrap * multiple Indexes objects into a context that can be used throughout the app. * In this case you will want to refer to an Indexes object by its Id in that * context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Indexes object or its * Id. * @category Identity * @since v1.0.0 */ export type IndexesOrIndexesId = Indexes | Id; /** * The RelationshipsOrRelationshipsId type is used when you need to refer to a * Relationships object in a React hook or component. * * In some simple cases you will already have a direct reference to the * Relationships object. * * This module also includes a Provider component that can be used to wrap * multiple Relationships objects into a context that can be used throughout the * app. In this case you will want to refer to a Relationships object by its Id * in that context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Relationships object * or its Id. * @category Identity * @since v1.0.0 */ export type RelationshipsOrRelationshipsId = Relationships | Id; /** * The QueriesOrQueriesId type is used when you need to refer to a Queries * object in a React hook or component. * * In some simple cases you will already have a direct reference to the Queries * object. * * This module also includes a Provider component that can be used to wrap * multiple Queries objects into a context that can be used throughout the app. * In this case you will want to refer to a Queries object by its Id in that * context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Queries object or its * Id. * @category Identity * @since v2.0.0 */ export type QueriesOrQueriesId = Queries | Id; /** * The CheckpointsOrCheckpointsId type is used when you need to refer to a * Checkpoints object in a React hook or component. * * In some simple cases you will already have a direct reference to the * Checkpoints object. * * This module also includes a Provider component that can be used to wrap * multiple Checkpoints objects into a context that can be used throughout the * app. In this case you will want to refer to a Checkpoints object by its Id in * that context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Checkpoints object or * its Id. * @category Identity * @since v1.0.0 */ export type CheckpointsOrCheckpointsId = Checkpoints | Id; /** * The PersisterOrPersisterId type is used when you need to refer to a Persister * object in a React hook or component. * * In some simple cases you will already have a direct reference to the * Persister object. * * This module also includes a Provider component that can be used to wrap * multiple Persister objects into a context that can be used throughout the * app. In this case you will want to refer to a Persister object by its Id in * that context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Persister or its Id. * @category Identity * @since v5.3.0 */ export type PersisterOrPersisterId = AnyPersister | Id; /** * The SynchronizerOrSynchronizerId type is used when you need to refer to a * Synchronizer object in a React hook or component. * * In some simple cases you will already have a direct reference to the * Synchronizer object. * * This module also includes a Provider component that can be used to wrap * multiple Synchronizer objects into a context that can be used throughout the * app. In this case you will want to refer to a Synchronizer object by its Id * in that context. * * Many hooks and components in this ui-react module take this type as a * parameter or a prop, allowing you to pass in either the Synchronizer or its * Id. * @category Identity * @since v5.3.0 */ export type SynchronizerOrSynchronizerId = Synchronizer | Id; /** * The UndoOrRedoInformation type is an array that you can fetch from a * Checkpoints object to that indicates if and how you can move the state of the * underlying Store forward or backward. * * This type is useful if you are building undo or redo buttons. See the * useUndoInformation hook and the useRedoInformation hook for more details and * examples. * @category Checkpoints * @since v1.0.0 */ export type UndoOrRedoInformation = [boolean, Callback, Id | undefined, string]; /** * The GetId type describes a function which, when passed a parameter, will * return an Id. * * This type is used in hooks that create callbacks - like the * useSetTableCallback hook or useSetRowCallback hook - so that the Id arguments * of the object to set can also be dependent on the event or parameter provided * (as well as the object itself being set). * @category Identity * @since v1.0.0 */ export type GetId<Parameter> = (parameter: Parameter, store: Store) => Id; /** * The useCreateStore hook is used to create a Store within a React application * with convenient memoization. * * It is possible to create a Store outside of the React app with the regular * createStore function and pass it in, but you may prefer to create it within * the app, perhaps inside the top-level component. To prevent a new Store being * created every time the app renders or re-renders, the useCreateStore hook * wraps the creation in a memoization. * * The useCreateStore hook is a very thin wrapper around the React `useMemo` * hook, defaulting to an empty array for its dependencies, so that by default, * the creation only occurs once. * * If your `create` function contains other dependencies, the changing of which * should cause the Store to be recreated, you can provide them in an array in * the optional second parameter, just as you would for any React hook with * dependencies. * @param create A function for performing the creation of the Store, plus any * additional steps such as adding data or listeners, and returning it. * @param createDeps An optional array of dependencies for the `create` * function, which, if any change, result in its rerun. This parameter defaults * to an empty array. * @returns A reference to the Store. * @example * This example creates an empty Store at the top level of a React application. * Even though the App component is rendered twice, the Store creation only * occurs once by default. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useCreateStore} from 'tinybase/ui-react'; * * const App = () => { * const store = useCreateStore(() => { * console.log('Store created'); * return createStore().setTables({pets: {fido: {species: 'dog'}}}); * }); * return <span>{store.getCell('pets', 'fido', 'species')}</span>; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App />); // !act * // -> 'Store created' * * root.render(<App />); // !act * // No second Store creation * * console.log(app.innerHTML); * // -> '<span>dog</span>' * ``` * @example * This example creates an empty Store at the top level of a React application. * The App component is rendered twice, each with a different top-level prop. * The useCreateStore hook takes the `fidoSpecies` prop as a dependency, and so * the Store is created again on the second render. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useCreateStore} from 'tinybase/ui-react'; * * const App = ({fidoSpecies}) => { * const store = useCreateStore(() => { * console.log(`Store created for fido as ${fidoSpecies}`); * return createStore().setTables({pets: {fido: {species: fidoSpecies}}}); * }, [fidoSpecies]); * return <span>{store.getCell('pets', 'fido', 'species')}</span>; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App fidoSpecies="dog" />); // !act * // -> 'Store created for fido as dog' * * console.log(app.innerHTML); * // -> '<span>dog</span>' * * root.render(<App fidoSpecies="cat" />); // !act * // -> 'Store created for fido as cat' * * console.log(app.innerHTML); * // -> '<span>cat</span>' * ``` * @category Store hooks * @since v1.0.0 */ export function useCreateStore( create: () => Store, createDeps?: React.DependencyList, ): Store; /** * The useCreateMergeableStore hook. * @category Store hooks * @since v1.0.0 */ export function useCreateMergeableStore( create: () => MergeableStore, createDeps?: React.DependencyList, ): MergeableStore; /** * The useStoreIds hook is used to retrieve the Ids of all the named Store * objects present in the current Provider component context. * @returns A list of the Ids in the context. * @example * This example adds two named Store objects to a Provider context and an inner * component accesses their Ids. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useCreateStore, useStoreIds} from 'tinybase/ui-react'; * * const App = () => { * const store1 = useCreateStore(createStore); * const store2 = useCreateStore(createStore); * return ( * <Provider storesById={{store1, store2}}> * <Pane /> * </Provider> * ); * }; * const Pane = () => <span>{JSON.stringify(useStoreIds())}</span>; * * const app = document.createElement('div'); * createRoot(app).render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>["store1","store2"]</span>' * ``` * @category Store hooks * @since v4.1.0 */ export function useStoreIds(): Ids; /** * The useStore hook is used to get a reference to a Store from within a * Provider component context. * * A Provider component is used to wrap part of an application in a context. It * can contain a default Store (or a set of Store objects named by Id) that can * be easily accessed without having to be passed down as props through every * component. * * The useStore hook lets you either get a reference to the default Store (when * called without a parameter), or one of the Store objects that are named by Id * (when called with an Id parameter). * @param id An optional Id for accessing a Store that was named with an Id in * the Provider. * @returns A reference to the Store (or `undefined` if not within a Provider * context, or if the requested Store does not exist). * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useStore hook to get a * reference to the Store again, without the need to have it passed as a prop. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useStore} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{useStore().getListenerStats().tables}</span>; * * const store = createStore(); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>0</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useStore hook with that Id to get * a reference to the Store again, without the need to have it passed as a prop. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useStore} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => ( * <span>{useStore('petStore').getListenerStats().tables}</span> * ); * * const store = createStore(); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>0</span>' * ``` * @category Store hooks * @since v1.0.0 */ export function useStore(id?: Id): Store | undefined; /** * The useStores hook is used to get a reference to all the Store objects named * by Id within a Provider component context. * * A Provider component is used to wrap part of an application in a context. It * can contain a default Store (or a set of Store objects named by Id) that can * be easily accessed without having to be passed down as props through every * component. * * The useStores hook lets you get a reference to the latter as an object. * @returns An object containing all the Store objects named by Id. * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useStores hook to get a reference * to the Store again. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useStores} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => ( * <span>{useStores()['petStore'].getListenerStats().tables}</span> * ); * * const store = createStore(); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>0</span>' * ``` * @category Store hooks * @since v5.4.1 */ export function useStores(): {[storeId: Id]: Store}; /** * The useStoreOrStoreById hook is used to get a reference to a Store object * from within a Provider component context, _or_ have it passed directly to * this hook. * * This is mostly of use when you are developing a component that needs a Store * object and which might have been passed in explicitly to the component or is * to be picked up from the context by Id (a common pattern for Store-based * components). * * This is unlikely to be used often. For most situations, you will want to use * the useStore hook. * @param storeOrStoreId Either an Id for accessing a Store object that was * named with an Id in the Provider, or the Store object itself. * @returns A reference to the Store object (or `undefined` if not within a * Provider context, or if the requested Store object does not exist). * @example * This example creates a Provider context into which a default Store object is * provided. A component within it then uses the useStoreOrStoreById hook to get * a reference to the Store object again, without the need to have it passed as * a prop. Note however, that unlike the useStore hook example, this component * would also work if you were to pass the Store object directly into it, making * it more portable. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useStoreOrStoreById} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = ({store}) => ( * <span>{JSON.stringify(useStoreOrStoreById(store).getTableIds())}</span> * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>["pets"]</span>' * ``` * @category Store hooks * @since v4.1.0 */ export function useStoreOrStoreById( storeOrStoreId?: StoreOrStoreId, ): Store | undefined; /** * The useProvideStore hook is used to add a Store object by Id to a Provider * component, but imperatively from a component within it. * * Normally you will register a Store by Id in a context by using the * `storesById` prop of the top-level Provider component. This hook, however, * lets you dynamically add a new Store to the context, from within a descendent * component. This is useful for applications where the set of Stores is not * known at the time of the first render of the root Provider. * * A Store added to the Provider context in this way will be available to other * components within the context (using the useStore hook and so on). If you use * the same Id as an existing Store registration, the new one will take priority * over one provided by the `storesById` prop. * * Note that other components that consume a Store registered like this should * defend against it being undefined at first. On the first render, the other * component will likely not yet have completed the registration. In the example * below, we use the null-safe `useStore('petStore')?` to do this. * @param storeId The Id of the Store object to be registered with the Provider. * @param store The Store object to be registered. * @example * This example creates a Provider context. A child component registers a Store * into it which is then consumable by a peer child component. * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import { * Provider, * useCreateStore, * useProvideStore, * useStore, * } from 'tinybase/ui-react'; * * const App = () => ( * <Provider> * <RegisterStore /> * <ConsumeStore /> * </Provider> * ); * const RegisterStore = () => { * const store = useCreateStore(() => * createStore().setCell('pets', 'fido', 'color', 'brown'), * ); * useProvideStore('petStore', store); * return null; * }; * const ConsumeStore = () => ( * <span>{JSON.stringify(useStore('petStore')?.getTableIds())}</span> * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>["pets"]</span>' * ``` * @category Store hooks * @since v4.4.2 */ export function useProvideStore(storeId: Id, store: Store): void; /** * The useHasTables hook returns a boolean indicating whether any Table objects * exist in the Store, and registers a listener so that any changes to that * result will cause a re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useHasTables hook lets you indicate which Store to get data for: omit the * optional parameter for the default context Store, provide an Id for a named * context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Tables will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns Whether any Tables exist. * @example * This example creates a Store outside the application, which is used in the * useHasTables hook by reference. A change to the data in the Store re-renders * the component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useHasTables} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => <span>{JSON.stringify(useHasTables(store))}</span>; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>true</span>' * * store.delTable('pets'); // !act * console.log(app.innerHTML); * // -> '<span>false</span>' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useHasTables hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useHasTables} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useHasTables())}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>true</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useHasTables hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useHasTables} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useHasTables('petStore'))}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>true</span>' * ``` * @category Store hooks * @since v4.4.0 */ export function useHasTables(storeOrStoreId?: StoreOrStoreId): boolean; /** * The useTables hook returns a Tables object containing the tabular data of a * Store, and registers a listener so that any changes to that result will cause * a re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useTables hook lets you indicate which Store to get data for: omit the * optional parameter for the default context Store, provide an Id for a named * context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Tables will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns A Tables object containing the tabular data of the Store. * @example * This example creates a Store outside the application, which is used in the * useTables hook by reference. A change to the data in the Store re-renders the * component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useTables} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => <span>{JSON.stringify(useTables(store))}</span>; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>{"pets":{"fido":{"color":"brown"}}}</span>' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '<span>{"pets":{"fido":{"color":"walnut"}}}</span>' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useTables hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTables} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useTables())}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>{"pets":{"fido":{"color":"brown"}}}</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useTables hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTables} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useTables('petStore'))}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>{"pets":{"fido":{"color":"brown"}}}</span>' * ``` * @category Store hooks * @since v1.0.0 */ export function useTables(storeOrStoreId?: StoreOrStoreId): Tables; /** * The useTableIds hook returns the Ids of every Table in a Store, and registers * a listener so that any changes to that result will cause a re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useTableIds hook lets you indicate which Store to get data for: omit the * optional parameter for the default context Store, provide an Id for a named * context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Table Ids will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns An array of the Ids of every Table in the Store. * @example * This example creates a Store outside the application, which is used in the * useTableIds hook by reference. A change to the data in the Store re-renders * the component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useTableIds} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => <span>{JSON.stringify(useTableIds(store))}</span>; * * const app = document.createElement('div'); * createRoot(app).render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>["pets"]</span>' * * store.setCell('species', 'dog', 'price', 5); // !act * console.log(app.innerHTML); * // -> '<span>["pets","species"]</span>' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useTableIds hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTableIds} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useTableIds())}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>["pets"]</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useTableIds hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTableIds} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useTableIds('petStore'))}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>["pets"]</span>' * ``` * @category Store hooks * @since v1.0.0 */ export function useTableIds(storeOrStoreId?: StoreOrStoreId): Ids; /** * The useHasTable hook returns a boolean indicating whether a given Table * exists in the Store, and registers a listener so that any changes to that * result will cause a re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useHasTable hook lets you indicate which Store to get data for: omit the * optional parameter for the default context Store, provide an Id for a named * context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Table will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param tableId The Id of the Table in the Store. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns Whether a Table with that Id exists. * @example * This example creates a Store outside the application, which is used in the * useHasTable hook by reference. A change to the data in the Store re-renders * the component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useHasTable} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * <span>{JSON.stringify(useHasTable('pets', store))}</span> * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>true</span>' * * store.delTable('pets'); // !act * console.log(app.innerHTML); * // -> '<span>false</span>' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useHasTable hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useHasTable} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useHasTable('pets'))}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>true</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useHasTable hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useHasTable} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => ( * <span>{JSON.stringify(useHasTable('pets', 'petStore'))}</span> * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>true</span>' * ``` * @category Store hooks * @since v4.4.0 */ export function useHasTable( tableId: Id, storeOrStoreId?: StoreOrStoreId, ): boolean; /** * The useTable hook returns an object containing the data of a single Table in * a Store, and registers a listener so that any changes to that result will * cause a re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useTable hook lets you indicate which Store to get data for: omit the final * optional final parameter for the default context Store, provide an Id for a * named context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Table will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param tableId The Id of the Table in the Store. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns An object containing the entire data of the Table. * @example * This example creates a Store outside the application, which is used in the * useTable hook by reference. A change to the data in the Store re-renders the * component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useTable} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => <span>{JSON.stringify(useTable('pets', store))}</span>; * * const app = document.createElement('div'); * createRoot(app).render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>{"fido":{"color":"brown"}}</span>' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '<span>{"fido":{"color":"walnut"}}</span>' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useTable hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTable} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useTable('pets'))}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>{"fido":{"color":"brown"}}</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useTable hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTable} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => ( * <span>{JSON.stringify(useTable('pets', 'petStore'))}</span> * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>{"fido":{"color":"brown"}}</span>' * ``` * @category Store hooks * @since v1.0.0 */ export function useTable(tableId: Id, storeOrStoreId?: StoreOrStoreId): Table; /** * The useTableCellIds hook returns the Ids of every Cell used across the whole * Table, and registers a listener so that any changes to that result will cause * a re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useTableCellIds hook lets you indicate which Store to get data for: omit the * optional final parameter for the default context Store, provide an Id for a * named context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Table Cell Ids will cause a re-render. When the component containing this * hook is unmounted, the listener will be automatically removed. * @param tableId The Id of the Table in the Store. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns An array of the Ids of every Cell used across the whole Table. * @example * This example creates a Store outside the application, which is used in the * useTableCellIds hook by reference. A change to the data in the Store * re-renders the component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useTableCellIds} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * <span>{JSON.stringify(useTableCellIds('pets', store))}</span> * ); * * const app = document.createElement('div'); * createRoot(app).render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>["color"]</span>' * * store.setCell('pets', 'felix', 'species', 'cat'); // !act * console.log(app.innerHTML); * // -> '<span>["color","species"]</span>' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useTableCellIds hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTableCellIds} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => <span>{JSON.stringify(useTableCellIds('pets'))}</span>; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>["color"]</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useTableCellIds hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useTableCellIds} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => ( * <span>{JSON.stringify(useTableCellIds('pets', 'petStore'))}</span> * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>["color"]</span>' * ``` * @category Store hooks * @since v3.3.0 */ export function useTableCellIds( tableId: Id, storeOrStoreId?: StoreOrStoreId, ): Ids; /** * The useHasTableCell hook returns a boolean indicating whether a given Cell * exists anywhere in a Table, not just in a specific Row, and registers a * listener so that any changes to that result will cause a re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useHasTableCell hook lets you indicate which Store to get data for: omit the * optional parameter for the default context Store, provide an Id for a named * context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Table will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param tableId The Id of the Table in the Store. * @param cellId The Id of the Cell in the Table. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns Whether a Cell with that Id exists anywhere in that Table. * @example * This example creates a Store outside the application, which is used in the * useHasTableCell hook by reference. A change to the data in the Store * re-renders the component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useHasTableCell} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * <span>{JSON.stringify(useHasTableCell('pets', 'legs', store))}</span> * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>false</span>' * * store.setRow('pets', 'felix', {color: 'black', legs: 4}); // !act * console.log(app.innerHTML); * // -> '<span>true</span>' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useHasTableCell hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useHasTableCell} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider store={store}> * <Pane /> * </Provider> * ); * const Pane = () => ( * <span>{JSON.stringify(useHasTableCell('pets', 'legs'))}</span> * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>false</span>' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useHasTableCell hook. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {Provider, useHasTableCell} from 'tinybase/ui-react'; * * const App = ({store}) => ( * <Provider storesById={{petStore: store}}> * <Pane /> * </Provider> * ); * const Pane = () => ( * <span> * {JSON.stringify(useHasTableCell('pets', 'legs', 'petStore'))} * </span> * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(<App store={store} />); // !act * console.log(app.innerHTML); * // -> '<span>false</span>' * ``` * @category Store hooks * @since v4.4.0 */ export function useHasTableCell( tableId: Id, cellId: Id, storeOrStoreId?: StoreOrStoreId, ): boolean; /** * The useRowCount hook returns the count of the Row objects in a given Table, * and registers a listener so that any changes to that result will cause a * re-render. * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Store or a set of Store objects named by Id. The * useRowCount hook lets you indicate which Store to get data for: omit the * optional final parameter for the default context Store, provide an Id for a * named context Store, or provide a Store explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * count of Row objects will cause a re-render. When the component containing * this hook is unmounted, the listener will be automatically removed. * @param tableId The Id of the Table in the Store. * @param storeOrStoreId The Store to be accessed: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @returns The number of Row objects in the Table. * @example * This example creates a Store outside the application, which is used in the * useRowCount hook by reference. A change to the data in the Store re-renders * the component. * * ```jsx * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * import {useRowCount} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => <span>{useRowCount('pets', store)}</span>; * * const app = document.createElement('div'); * createRoot(app).render(<App />); // !act * console.log(app.innerHTML); * // -> '<span>1</span>' * * store.setCell('pets', 'felix', 'color', 'black'); // !act * console.log(app.innerHTML); * // -> '<span>2</span>' * ``` * @example * This