S
SolidJS11mo ago
Nathan

Trouble porting a React hook to Solid

I'm trying to port the usePlaidLink hook to Solid. But after making some adjustments from the React version, I'm getting a stack overflow error in a basic rendering test. This is what I have:
export const createPlaidLink = (options: PlaidLinkOptions) => {
const [loading, error] = useScript(PLAID_LINK_STABLE_URL);

const [plaid, setPlaid] = createSignal<PlaidFactory | null>();
const [iframeLoaded, setIframeLoaded] = createSignal(false);
const products = ((options as PlaidLinkOptionsWithPublicKey).product || [])
.slice()
.sort()
.join(",");

createEffect(() => {
if (loading()) {
console.log(`loading: ${loading()}`);
return;
}

if (
!options.token &&
!(options as PlaidLinkOptionsWithPublicKey).publicKey
) {
console.log("no token");
return;
}

if (error() || !window.Plaid) {
console.error("Error loading Plaid", error);
}

// exit
if (plaid() != null) {
plaid()!.exit({ force: true }, () => plaid()!.destroy());
}

const next = createPlaid(
{
...options,
onLoad: () => {
setIframeLoaded(true);
options.onLoad && options.onLoad();
},
},
window.Plaid.create
);

setPlaid(next);

onCleanup(() => {
next.exit({ force: true }, () => next.destroy());
});
});

const ready = createMemo(
() => plaid() != null && (!loading || iframeLoaded())
);

const openNoOp = () => {
if (!options.token) {
console.warn(
"solid-plaid-link: You cannot call open() without a valid token supplied to usePlaidLink. This is a no-op."
);
}
};

return {
error,
ready,
exit: plaid() ? plaid()!.exit : noop,
open: plaid() ? plaid()!.open : openNoOp,
};
};
export const createPlaidLink = (options: PlaidLinkOptions) => {
const [loading, error] = useScript(PLAID_LINK_STABLE_URL);

const [plaid, setPlaid] = createSignal<PlaidFactory | null>();
const [iframeLoaded, setIframeLoaded] = createSignal(false);
const products = ((options as PlaidLinkOptionsWithPublicKey).product || [])
.slice()
.sort()
.join(",");

createEffect(() => {
if (loading()) {
console.log(`loading: ${loading()}`);
return;
}

if (
!options.token &&
!(options as PlaidLinkOptionsWithPublicKey).publicKey
) {
console.log("no token");
return;
}

if (error() || !window.Plaid) {
console.error("Error loading Plaid", error);
}

// exit
if (plaid() != null) {
plaid()!.exit({ force: true }, () => plaid()!.destroy());
}

const next = createPlaid(
{
...options,
onLoad: () => {
setIframeLoaded(true);
options.onLoad && options.onLoad();
},
},
window.Plaid.create
);

setPlaid(next);

onCleanup(() => {
next.exit({ force: true }, () => next.destroy());
});
});

const ready = createMemo(
() => plaid() != null && (!loading || iframeLoaded())
);

const openNoOp = () => {
if (!options.token) {
console.warn(
"solid-plaid-link: You cannot call open() without a valid token supplied to usePlaidLink. This is a no-op."
);
}
};

return {
error,
ready,
exit: plaid() ? plaid()!.exit : noop,
open: plaid() ? plaid()!.open : openNoOp,
};
};
I can tell it's cycling endlessly through the exit, setPlaid(next), and onCleanup phases of the createEffect. Any idea what's happening?
2 Replies
lxsmnsyc
lxsmnsyc11mo ago
You're also tracking plaid() so it's basically a recursion. Same thing will happen to React if plaid is a dependency.
Nathan
Nathan11mo ago
Yup, that fixed it. Thanks!