I am a Dev
I am a Dev10mo ago

Hello, is there any way to create a base router with common procedures? like an interface

I want all routers that use it have the state procedure (subscriptions), so I can create a common hook later Although the implementation of the methods is completely different on each router, I just want to guarantee that they have those procedures, like an interface The hook basically will subscribe to the state on mount, and unsubscribe on unmount Thanks
3 Replies
I am a Dev
I am a Dev10mo ago
I have something like this:
import { useEffect, useState } from 'react';
import type { Unsubscribable } from '@trpc/server/observable';
import type {} from '@trpc/client/src/';

interface UseRouterStateOptions<TState> {
stateSubscribe: (
input: undefined,
opts: { onData: (state: TState) => void },
) => Unsubscribable;
}

export function useRouterState<TState>(
opts: UseRouterStateOptions<TState>,
): TState | null {
const [state, setState] = useState<TState | null>(null);

useEffect(() => {
const stateSubscription = opts.stateSubscribe(undefined, {
onData: (data) => {
setState(data);
},
});

return () => {
stateSubscription.unsubscribe();
};
}, []);

return state;
}
import { useEffect, useState } from 'react';
import type { Unsubscribable } from '@trpc/server/observable';
import type {} from '@trpc/client/src/';

interface UseRouterStateOptions<TState> {
stateSubscribe: (
input: undefined,
opts: { onData: (state: TState) => void },
) => Unsubscribable;
}

export function useRouterState<TState>(
opts: UseRouterStateOptions<TState>,
): TState | null {
const [state, setState] = useState<TState | null>(null);

useEffect(() => {
const stateSubscription = opts.stateSubscribe(undefined, {
onData: (data) => {
setState(data);
},
});

return () => {
stateSubscription.unsubscribe();
};
}, []);

return state;
}
And in the widget I should use this:
const state = useRouterState({
stateSubscribe:
tRPCClient.router1.router2.state.subscribe,
});
const state = useRouterState({
stateSubscribe:
tRPCClient.router1.router2.state.subscribe,
});
But i want to only pass the router as a argument, because i want to return more properties that only the state I'm using electron-trpc, so basically the router is like a store, so I can use all the node logic in the main process, but subscribe to the state in the renderer. And because I have more than 30 store like this, want to create common hooks and interfaces
Nick
Nick10mo ago
You probably want a Router Factory, and may want to use our Polymorphism types on the frontend too: https://dev.to/nicklucas/trpc-patterns-router-factories-and-polymorphism-30b0
DEV Community
tRPC & React Patterns: Router Factories
This post comes in 2 halves: tRPC Router Factories Consuming Router Factories in a React...
Nick
Nick10mo ago
It does take a certain amount of confidence with Typescript to use this pattern, but sounds like it's exactly your use case This said, subscriptions aren't currently in the polymorphism types simply because we haven't added them, so YMMV