Next.js Discord

Discord Forum

State doesn't seem to cause a re-render. Next.js 14 (app router, client component)

Answered
SpicyJungle posted this in #help-forum
Open in Discord
i'm having an issue with nextjs 14 app router here. might be an obvious issue but I can't find it.

The guild state here doesn't seem to cause a re-render of the component, at least when I pass the guild prop down it doesn't change any of the data i use with it.
dashboard/page.tsx
          <h2 className="text-2xl text-white font-bold">Your Servers</h2>
          {guilds &&
            guilds.map((guild) => {
              const isCommon = commonGuilds.find(
                (g: dbGuild) => g.guildId === guild.id
              );

              return (
                <HoverCard key={guild.id}>
                  <HoverCardTrigger
                    className="w-full bg-black/40 p-2 text-white rounded-md hover:scale-105 transition-all"
                    onClick={() => {
                      if (!isCommon) return;
                      setGuild({ ...isCommon, ...guild }) // <--- I update state here
                    }}
                  >
                    {guild.name}
                  </HoverCardTrigger>

...
// this is in the same component as above:
        <div className="main h-full w-full bg-black/40 rounded-md">
          {guild ? <Dash guild={guild} /> : <h1 className="w-full text-center mt-20 text-xl text-white">Select a server to begin.</h1>}
                          //    ^ this doesn't update (so I'm guessing it doesn't rerender)        
</div>
Answered by joulev
Maybe add a key to force update? <Dash guild={guild} key={guild.id} />
View full answer

14 Replies

Bump
@Ray try add a console.log here ts onClick={() => { if (!isCommon) return; const newGuild = { ...isCommon, ...guild } console.log(newGuild) setGuild(newGuild) }}
It does log the new guild i want to display
Thinking about it, I display the guild name somewhere else, and it updates as intended. So it does rerender and i'm messing up somewhere else
Answer
Sometimes react is too aggressive in caching the component
found the place of error, not sure how to solve. So in i'm adding a way to blacklist certain articles. This is the code for the states of the component + the function that sends a request to blacklist it.

const BlacklistedArticles = ({ guild }: { guild: ExtendedGuild }) => {
  const [article, setArticle] = useState("");
  const [blacklisted, setBlacklisted] = useState<string[]>(
    guild.blacklistedArticles
  );

  console.log("CURRENT BLACKLISTED", blacklisted)
  console.log("GUILD BLACKLIST", guild.blacklistedArticles)

  const sendReq = async () => {
    if (!article) return;
    setArticle("");
    const prevBlacklist = blacklisted;
    setBlacklisted([...blacklisted, article]);

    const res = await axios
      .post(
        `/api/discord/blacklist?guild=${guild.id}&type=article&article=${article}`
      )
      .catch((e: AxiosError) => {
        setBlacklisted(prevBlacklist);
        toast.error(
          "Failed to blacklist article: " + e.response?.data ?? "Unkown error"
        );
      });

    if (!res) return;
    guild.blacklistedArticles.push(article);
    toast.success("Successfully blacklisted article.");
  };

  ...


On the two console.log statements, i see the blacklisted state doesn't clear when changing guild
thank you so much 😭 🙏
TIL
though i guess that does make sense
Yeah you would probably want to use only a single source of truth and consume + update the guild value directly rather than use a separate state for the guild.blacklistedArticles