TinyBase logoTinyBase

useCreatePersister

The useCreatePersister hook is used to create a Persister within a React application along with convenient memoization and callbacks.

useCreatePersister<PersisterOrUndefined>(
  store: Store,
  create: (store: Store) => PersisterOrUndefined,
  createDeps?: DependencyList,
  then?: (persister: PersisterOrUndefined) => Promise<void>,
  thenDeps?: DependencyList,
  destroy?: (persister: PersisterOrUndefined) => void,
  destroyDeps?: DependencyList,
): PersisterOrUndefined
TypeDescription
storeStore

A reference to the Store for which to create a new Persister object.

create(store: Store) => PersisterOrUndefined

A function for performing the creation steps of the Persister object for the Store.

createDeps?DependencyList

An optional array of dependencies for the create function, which, if any change, result in its rerun. This parameter defaults to an empty array.

then?(persister: PersisterOrUndefined) => Promise<void>

An optional callback for performing asynchronous post-creation steps on the Persister, such as starting automatic loading and saving.

thenDeps?DependencyList

An optional array of dependencies for the then callback, which, if any change, result in its rerun. This parameter defaults to an empty array.

destroy?(persister: PersisterOrUndefined) => void

An optional callback whenever the Persister is destroyed due to a change in the createDeps dependencies.

destroyDeps?DependencyList

An optional array of dependencies for the destroy callback, which, if any change, result in destroy and then being rerun. This parameter defaults to an empty array.

returnsPersisterOrUndefined

A reference to the Persister.

It is possible to create a Persister outside of the React app with the regular createPersister function and pass it in, but you may prefer to create it within the app, perhaps inside the top-level component. To defend against a new Persister being created every time the app renders or re-renders, the useCreatePersister hook wraps the creation in a memoization, and provides a second callback so that you can configure the Persister, once, and asynchronously, when it is created.

If your create function (the second parameter to the hook) contains dependencies, the changing of which should cause the Persister to be recreated, you can provide them in an array in the third parameter, just as you would for any React hook with dependencies. The Store passed in as the first parameter of this hook is used as a dependency by default.

A second then callback can be provided as the fourth parameter. This is called after the creation, and, importantly, can be asynchronous, so that you can configure the Persister with the startAutoLoad method and startAutoSave method, for example. If this callback contains dependencies, the changing of which should cause the Persister to be reconfigured, you can provide them in an array in the fifth parameter. The Persister itself is used as a dependency by default.

Since v4.3.0, the create function can return undefined, meaning that you can enable or disable persistence conditionally within this hook. This is useful for applications which might turn on or off their cloud persistence or collaboration features. As a result, the then callback may also get passed undefined, which you should handle accordingly.

Since v4.3.19, a destroy function can be provided which will be called after an old Persister is destroyed due to a change in the createDeps dependencies that causes a new one to be created. Use this to clean up any underlying storage objects that you set up during the then function, for example. If this callback itself contains additional dependencies, you can provide them in an array in the seventh parameter.

This hook ensures the Persister object is destroyed whenever a new one is created or the component is unmounted.

Examples

This example creates a Persister at the top level of a React application. Even though the App component is rendered twice, the Persister creation only occurs once by default.

const App = () => {
  const store = useCreateStore(createStore);
  const persister = useCreatePersister(
    store,
    (store) => {
      console.log('Persister created');
      return createSessionPersister(store, 'pets');
    },
    [],
    async (persister) => {
      await persister.startAutoLoad();
      await persister.startAutoSave();
    },
  );
  return <span>{JSON.stringify(useTables(store))}</span>;
};

sessionStorage.setItem(
  'pets',
  '[{"pets":{"fido":{"species":"dog"}}}, {}]',
);

const app = document.createElement('div');
const root = ReactDOMClient.createRoot(app);
root.render(<App />);
// -> 'Persister created'

// ...
root.render(<App />);
// No second Persister creation

console.log(app.innerHTML);
// -> '<span>{\"pets\":{\"fido\":{\"species\":\"dog\"}}}</span>'

root.unmount();

This example creates a Persister at the top level of a React application. The App component is rendered twice, each with a different top-level prop. The useCreatePersister hook takes the sessionKey prop as a dependency, and so the Persister object is created again on the second render. The first is destroyed and the destroy parameter is called for it.

const App = ({sessionKey}) => {
  const store = useCreateStore(createStore);
  const persister = useCreatePersister(
    store,
    (store) => {
      console.log(`Persister created for session key ${sessionKey}`);
      return createSessionPersister(store, sessionKey);
    },
    [sessionKey],
    async (persister) => {
      await persister.startAutoLoad();
    },
    [],
    (persister) =>
      console.log(
        `Persister destroyed for session key ${persister.getStorageName()}`,
      ),
  );
  return <span>{JSON.stringify(useTables(store))}</span>;
};

sessionStorage.setItem(
  'fidoStore',
  '[{"pets":{"fido":{"species":"dog"}}}, {}]',
);
sessionStorage.setItem(
  'cujoStore',
  '[{"pets":{"cujo":{"species":"dog"}}}, {}]',
);

const app = document.createElement('div');
const root = ReactDOMClient.createRoot(app);
root.render(<App sessionKey="fidoStore" />);
// -> 'Persister created for session key fidoStore'

// ...
console.log(app.innerHTML);
// -> '<span>{\"pets\":{\"fido\":{\"species\":\"dog\"}}}</span>'

root.render(<App sessionKey="cujoStore" />);
// -> 'Persister created for session key cujoStore'
// -> 'Persister destroyed for session key fidoStore'

// ...
console.log(app.innerHTML);
// -> '<span>{\"pets\":{\"cujo\":{\"species\":\"dog\"}}}</span>'

root.unmount();
// -> 'Persister destroyed for session key cujoStore'