Skip to main content

React Helpers

RemNote React Helper Hooks

We've provided a number of helper hooks to make it easier to write clean functional React components.

Reactive Method Hooks (useTracker)

See the Tracker system docs.

Non-Reactive Method Hooks

useRunAsync

The useRunAsync simplifies calling of async plugin API methods inside the rendering code of React components.

Consider the following example where we have a variable containing some rich text and we want to convert it to a normal string so we can work with it inside our component.

export const MyComponent = () => {
const plugin = usePlugin();
const richText: RichTextInterface = ...
// convert to string
const str = ...
}

The function to convert RichTextInterfaces to string is the toString method in the richText namespace. Like the rest of the plugin API methods it is an async method, so our first instinct is to call it like this: await plugin.richText.toString(...). Unfortunately, this isn't possible within the rendering code of React components without wrapping the async code inside a useEffect hook and using useState to record the result of the async function.

export const MyComponent = () => {
const plugin = usePlugin();
const richText: RichTextInterface = ...
// not possible - can't await async functions here
// const str = await plugin.richText.toString(richText)
// we could use useEffect and useState, but it's pretty messy
const [str, setStr] = useState();
useEffect(() => {
const setStr = async () => {
setStr(await plugin.richText.toString(richText));
}
setStr();
}, [richText])
}

A better option is to use the useRunAsync hook which simplifies our code dramatically by allowing us to call the function inline:

export const MyComponent = () => {
const plugin = usePlugin();
const richText: RichTextInterface = ...
// useRunAsync allows us to call the async
// plugin.richText.toString function inline, rather
// than needing to wrap things in useEffect and setState
const str = useRunAsync(
async () => await plugin.richText.toString(richText), // function we want to call
[richText], // dependences (like useEffect)
)
}

Note that hooks cannot be called conditionally or inside loops because it can change the order in which hooks are called, preventing React from tracking the state of your component between rerenders. So the following code will cause errors:

if (condition) {
const str = useRunAsync(plugin.richText.toString, [], richText);
}

If you need to call the function conditionally, move the condition inside the function parameter:

const str = useRunAsync(async () => {
if (condition) {
await plugin.richText.toString(richText);
}
}, [richText]);

See the the API documentation page for more details.

useAPIEventListener

The useAPIEventListener hook simplifies subscribing to plugin events in components - rather than needing to use useEffect to add and remove plugin event listeners, you can use the useAPIEventListener hook to subscribe to events inline without having to write any boilerplate code:

useAPIEventListener(AppEvents.GlobalRemChanged, undefined, async (data) => {
if (data.remId) {
const rem = await plugin.rem.findOne(data.remId);
setRemWordsMap(Re.set(rem.id, allRemText(rem)));
}
});

Please see the events documentation page for more examples and see the the API documentation page for more details on the useAPIEventListener hook.

Storage Hooks

See the storage documentation