diff --git a/src/useReplicant/index.ts b/src/useReplicant/index.ts index b2e15af..69c4ef3 100644 --- a/src/useReplicant/index.ts +++ b/src/useReplicant/index.ts @@ -1,49 +1,46 @@ import {useEffect, useState} from 'react'; import clone from 'lodash.clone'; - -export interface UseReplicantOptions { - namespace: string; -} +import {ReplicantOptions} from 'nodecg/types/server'; /** * Subscribe to a replicant, returns tuple of the replicant value and `setValue` function. * The component using this function gets re-rendered when the value is updated. * The `setValue` function can be used to update replicant value. - * @param repName The name of the replicant to use + * @param replicantName The name of the replicant to use * @param initialValue Initial value to pass to `useState` function * @param options Options object. Currently supports the optional `namespace` option */ -export const useReplicant = ( - repName: string, - initialValue: T, - options?: UseReplicantOptions, -): [T, (newValue: T) => void] => { - // Local state to store replicant value - const [value, updateValue] = useState(initialValue); +export const useReplicant = ( + replicantName: string, + initialValue: U, + options?: ReplicantOptions & {namespace?: string}, +): [T | U, (newValue: T) => void] => { + const [value, updateValue] = useState(initialValue); - // Declare replicant - let replicant: any; - if (options && options.namespace) { - replicant = nodecg.Replicant(repName, options.namespace, { - defaultValue: initialValue, - }); - } else { - replicant = nodecg.Replicant(repName, { - defaultValue: initialValue, - }); - } + const replicantOptions = options && { + defaultValue: options.defaultValue, + persistent: options.persistent, + schemaPath: options.schemaPath, + }; + const replicant = + options && options.namespace + ? nodecg.Replicant( + replicantName, + options.namespace, + replicantOptions, + ) + : nodecg.Replicant(replicantName, replicantOptions); - // Change handler to listen replicant changes const changeHandler = (newValue: T): void => { updateValue((oldValue) => { if (newValue !== oldValue) { return newValue; } + // replicant.value has always the same reference. Cloning to cause re-rendering return clone(newValue); }); }; - // Uses no state directly, removes listener on unmount useEffect(() => { replicant.on('change', changeHandler); return () => { @@ -51,10 +48,10 @@ export const useReplicant = ( }; }, [replicant]); - // Function to set replicant value - const updateRepValue = (newValue: T): void => { - replicant.value = newValue; - }; - - return [value, updateRepValue]; + return [ + value, + (newValue) => { + replicant.value = newValue; + }, + ]; };