How do I set the default useState value of a trpc call?

EDIT: Sorry apparently I can't rename the title. I meant to say: 'How do I set a default useState value to something that came from a trpc call' Hi folks, so I need some help with my component It's a simple team switcher. I need help understanding a few things. I have two main trpc endpoints: getAllForLoggedUser and switchActiveWorkspace. one thing: whenever I am reloading this component fresh new, I am not being able to set the default value of the useState call. The default value is not being set. How can I make it so it sets the default value that came from the trpc call
export default function TeamSwitcher({ className }: TeamSwitcherProps) {
const ctx = api.useContext();
const { data: session } = useSession();

const { data: workspaces } = api.workspace.getAllForLoggedUser.useQuery(
undefined,
{
enabled: session?.user !== undefined,
}
);

const { mutateAsync } = api.user.switchActiveWorkspace.useMutation({
onSuccess: () => {
void ctx.workspace.getAllForLoggedUser.invalidate();
},
});

const [selectedWS, setSelectedWS] = React.useState<Workspace>({
id: session?.user?.activeWorkspaceId || "",
name:
workspaces?.find((w) => w.id === session?.user?.activeWorkspaceId)
?.name || "", //This was supposed to be working 🥲
});

return (
{/*tsx Code.
At some point there is a mapping of the workspaces array and on each item there is a onSelect like this
onSelect={() => {
setSelectedWS({
id: ws.id,
name: ws.name,
});
setOpen(false);
void mutateAsync({ workspaceId: ws.id });
}}
*/}
)
}
export default function TeamSwitcher({ className }: TeamSwitcherProps) {
const ctx = api.useContext();
const { data: session } = useSession();

const { data: workspaces } = api.workspace.getAllForLoggedUser.useQuery(
undefined,
{
enabled: session?.user !== undefined,
}
);

const { mutateAsync } = api.user.switchActiveWorkspace.useMutation({
onSuccess: () => {
void ctx.workspace.getAllForLoggedUser.invalidate();
},
});

const [selectedWS, setSelectedWS] = React.useState<Workspace>({
id: session?.user?.activeWorkspaceId || "",
name:
workspaces?.find((w) => w.id === session?.user?.activeWorkspaceId)
?.name || "", //This was supposed to be working 🥲
});

return (
{/*tsx Code.
At some point there is a mapping of the workspaces array and on each item there is a onSelect like this
onSelect={() => {
setSelectedWS({
id: ws.id,
name: ws.name,
});
setOpen(false);
void mutateAsync({ workspaceId: ws.id });
}}
*/}
)
}
7 Replies
gybia
gybia2y ago
Here's the full code if needed
Neto
Neto2y ago
put the useState above the queries onSuccess of the query, update the state
export default function TeamSwitcher({ className }: TeamSwitcherProps) {
const ctx = api.useContext();
const { data: session } = useSession();

const [selectedWS, setSelectedWS] = React.useState<some_type>({
id: session?.user?.activeWorkspaceId || "",
name:
workspaces?.find((w) => w.id === session?.user?.activeWorkspaceId)
?.name || "", //This was supposed to be working 🥲
});


const { data: workspaces } = api.workspace.getAllForLoggedUser.useQuery(
undefined,
{
enabled: session?.user !== undefined,
onSuccess: (data) => {
const newSelectedWS = some_logic_goes_where
setSelectedWS(newSelectedWS)
}
}
);

const { mutateAsync } = api.user.switchActiveWorkspace.useMutation({
onSuccess: () => {
void ctx.workspace.getAllForLoggedUser.invalidate();
},
});


return (
<></>
)
}
export default function TeamSwitcher({ className }: TeamSwitcherProps) {
const ctx = api.useContext();
const { data: session } = useSession();

const [selectedWS, setSelectedWS] = React.useState<some_type>({
id: session?.user?.activeWorkspaceId || "",
name:
workspaces?.find((w) => w.id === session?.user?.activeWorkspaceId)
?.name || "", //This was supposed to be working 🥲
});


const { data: workspaces } = api.workspace.getAllForLoggedUser.useQuery(
undefined,
{
enabled: session?.user !== undefined,
onSuccess: (data) => {
const newSelectedWS = some_logic_goes_where
setSelectedWS(newSelectedWS)
}
}
);

const { mutateAsync } = api.user.switchActiveWorkspace.useMutation({
onSuccess: () => {
void ctx.workspace.getAllForLoggedUser.invalidate();
},
});


return (
<></>
)
}
gybia
gybia2y ago
@Neto But this way, workspace (where the useState is invoked) will be used before it's being defined. OOh I see what you mean
Neto
Neto2y ago
if the state is derived from the query you can make a "blank" state and update when the query finishes
gybia
gybia2y ago
This fixed it!! Thank you so much ❤️
whatplan
whatplan2y ago
while this does work its probably not ideal: https://tkdodo.eu/blog/breaking-react-querys-api-on-purpose
Breaking React Query's API on purpose
Why good API design matters, even if it means breaking existing APIs in the face of resistance.
Want results from more Discord servers?
Add your server