Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options objects so we can have namespace/bundle support #2

Merged
merged 1 commit into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/useListenFor/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import {useEffect} from 'react';

export interface UseListenForOptions {
bundle: string;
}

export const useListenFor = <T>(
messageName: string,
handler: (message: T) => void,
options?: UseListenForOptions,
): void => {
useEffect(() => {
if (options && options.bundle) {
nodecg.listenFor(messageName, options.bundle, handler);
return () => {
nodecg.unlisten(messageName, options.bundle, handler);
};
}
nodecg.listenFor(messageName, handler);
return () => {
nodecg.unlisten(messageName, handler);
Expand Down
19 changes: 16 additions & 3 deletions src/useReplicant/index.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
import {useEffect, useState} from 'react';
import clone from 'lodash.clone';

export interface UseReplicantOptions {
namespace: string;
}

/**
* 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 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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd become simpler with initialValue combined with options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some way to do runtime checking of a type? Or do I basically have to check if options has any of the options arguments (bundle, namespace, etc) and if not, then treat it like an initial value? Like:

if (object && object.namespace)
  // I'm an options
else 
  // I'm an initialivalue

?

Copy link
Contributor

@CarlosFdez CarlosFdez Apr 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately given how flexible Replicants are, I don't think merging them will work. The only real choice I can think of here is to remove initialValue and use options instead. Options provides a defaultValue parameter as a substitute.

It'd be a breaking change but pre-release that's not too big a deal. You could also handle it by making a separate function and making the existing one proxy to that one.

): [T, (newValue: T) => void] => {
// Local state to store replicant value
const [value, updateValue] = useState<T>(initialValue);

// Declare replicant
const replicant = nodecg.Replicant(repName, {
defaultValue: initialValue,
});
let replicant: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, the function nodecg.Replicant() returns a value with type Replicant (confusing but that's what happens...). It may be possible to avoid any here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I'll check that out. I wasn't aware of any of the nodecg types.

if (options && options.namespace) {
replicant = nodecg.Replicant(repName, options.namespace, {
defaultValue: initialValue,
});
} else {
replicant = nodecg.Replicant(repName, {
defaultValue: initialValue,
});
}

// Change handler to listen replicant changes
const changeHandler = (newValue: T): void => {
Expand Down
17 changes: 14 additions & 3 deletions src/useReplicantOnce/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import {useState} from 'react';

export interface UseReplicantOnceOptions {
bundle: string;
}

export const useReplicantOnce = <T>(
replicantName: string,
initialValue: T,
options?: UseReplicantOnceOptions,
): T => {
const [state, setState] = useState(initialValue);
nodecg.readReplicant<T>(replicantName, (value) => {
setState(value);
});
if (options && options.bundle) {
nodecg.readReplicant<T>(replicantName, options.bundle, (value) => {
setState(value);
});
} else {
nodecg.readReplicant<T>(replicantName, (value) => {
setState(value);
});
}
return state;
};