Skip to content

Commit

Permalink
feat(useReplicant): allow initialValue to be different type
Browse files Browse the repository at this point in the history
  • Loading branch information
Hoishin committed Apr 30, 2019
1 parent 0882d97 commit 69bd903
Showing 1 changed file with 28 additions and 31 deletions.
59 changes: 28 additions & 31 deletions src/useReplicant/index.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,57 @@
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 = <T>(
repName: string,
initialValue: T,
options?: UseReplicantOptions,
): [T, (newValue: T) => void] => {
// Local state to store replicant value
const [value, updateValue] = useState<T>(initialValue);
export const useReplicant = <T, U>(
replicantName: string,
initialValue: U,
options?: ReplicantOptions<T> & {namespace?: string},
): [T | U, (newValue: T) => void] => {
const [value, updateValue] = useState<T | U>(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 () => {
replicant.removeListener('change', changeHandler);
};
}, [replicant]);

// Function to set replicant value
const updateRepValue = (newValue: T): void => {
replicant.value = newValue;
};

return [value, updateRepValue];
return [
value,
(newValue) => {
replicant.value = newValue;
},
];
};

0 comments on commit 69bd903

Please sign in to comment.