Types
Answered
Blue Picardy Spaniel posted this in #help-forum
Blue Picardy SpanielOP
export const GuildProvider: React.FC<{ initialGuilds: UserGuild[] | null, children: ReactNode }> = ({ initialGuilds, children }) => {
const router = useRouter();
const [guilds, setGuilds] = useState<UserGuild[] | null>(initialGuilds);
if(!initialGuilds) router.push("/api/auth"); // REDIRECT IS HERE
const updateGuildSetting = (guildID: string, settingKey: string, value: SettingValue) => {
setGuilds(prevGuilds => {
if(!prevGuilds) return null;
const newSettings = prevGuilds.map(guild =>
guild.id === guildID
? { ...guild, settings: { ...guild.settings, [settingKey]: value } } as UserGuild
: guild
);
setGuildSetting(guildID, settingKey, value);
return newSettings;
});
};
return (
<GuildContext.Provider value={{ guilds, updateGuildSetting }}>
{children}
</GuildContext.Provider>
);
};Currently, guilds is typed as
UserGuild[] | null, however since I'm redirecting the user if they have no initialGuilds, guilds type is technically UserGuild[]. How do I reflect this to TypeScript when I pass the guilds variable to my provider?Answered by B33fb0n3
Of course not inside the clientside file (provider). There, where you use the component. Like:
const guilds = await getUserGuilds();
if(!guilds)
redirect("/");
return <div>
<GuildProvider initialGuilds={guilds}>
<p>Some other components</p>
</GuildProvider>
</div>11 Replies
@B33fb0n3 return after redirect. So like:
tsx
if(!initialGuilds) {
router.push("/api/auth"); // REDIRECT IS HERE
return;
}
Blue Picardy SpanielOP
this works for initialGuilds however since im passing guilds to the provider,
guilds still shows as possibly null@Blue Picardy Spaniel this works for initialGuilds however since im passing guilds to the provider, `guilds` still shows as possibly null
oh my bad. Replace
initialGuilds with guilds (your useState) and your context can only be set. I couldn't directly see the type of your context, but I guess that should currently be UserGild[] | null & the function to update@B33fb0n3 oh my bad. Replace initialGuilds with guilds (your useState) and your context can only be set. I couldn't directly see the type of your context, but I guess that should currently be UserGild[] | null & the function to update
Blue Picardy SpanielOP
this is gonna sound really picky but one issue with this is that when i log out, i don't get redirected. i have to refresh to get redirected, but when i do initialGuilds instead of guilds, it redirects instantly. im not sure why that is
@Blue Picardy Spaniel this is gonna sound really picky but one issue with this is that when i log out, i don't get redirected. i have to refresh to get redirected, but when i do initialGuilds instead of guilds, it redirects instantly. im not sure why that is
can you redirect serverside instead of clientside?
@B33fb0n3 can you redirect serverside instead of clientside?
Blue Picardy SpanielOP
no since this is in a client file
"use client";
import type { ReactNode } from "react";
import React, { createContext, useState, useContext } from "react";
import { useRouter } from "next/navigation";
import type { UserGuild } from "@/types/guilds";
import { setGuildSetting } from "@/db/access/guilds";
import type { SettingValue } from "@/types/settings";
interface GuildContextType {
guilds: UserGuild[] | null;
updateGuildSetting: (guildId: string, settingKey: string, value: SettingValue) => void;
}
const GuildContext = createContext<GuildContextType | undefined>(undefined);
export const GuildProvider: React.FC<{ initialGuilds: UserGuild[] | null, children: ReactNode }> = ({ initialGuilds, children }) => {
const router = useRouter();
const [guilds, setGuilds] = useState<UserGuild[] | null>(initialGuilds);
if(!initialGuilds) {
router.push("/api/auth");
return;
}
const updateGuildSetting = (guildID: string, settingKey: string, value: SettingValue) => {
setGuilds(prevGuilds => {
if(!prevGuilds) return null;
const newSettings = prevGuilds.map(guild =>
guild.id === guildID
? { ...guild, settings: { ...guild.settings, [settingKey]: value } } as UserGuild
: guild
);
setGuildSetting(guildID, settingKey, value);
return newSettings;
});
};
return (
<GuildContext.Provider value={{ guilds, updateGuildSetting }}>
{children}
</GuildContext.Provider>
);
};
export const useGuilds = (): GuildContextType => {
const context = useContext(GuildContext);
if(context === undefined) throw new Error("useGuilds must be used within a GuildProvider");
return context;
};@Blue Picardy Spaniel no since this is in a client file
Of course not inside the clientside file (provider). There, where you use the component. Like:
const guilds = await getUserGuilds();
if(!guilds)
redirect("/");
return <div>
<GuildProvider initialGuilds={guilds}>
<p>Some other components</p>
</GuildProvider>
</div>Answer
@B33fb0n3 Of course not inside the clientside file (provider). There, where you use the component. Like:
tsx
const guilds = await getUserGuilds();
if(!guilds)
redirect("/");
return <div>
<GuildProvider initialGuilds={guilds}>
<p>Some other components</p>
</GuildProvider>
</div>
Blue Picardy SpanielOP
godsend, thanks man
feel free to change the solution to the correct message if I missed the correct one