Client component state not updated if server side data props updated
Unanswered
Spectacled bear posted this in #help-forum
Spectacled bearOP
Hey,
I have a Client component that get props from Layout server component (a chat sidebar).
When a new conversation is created, I revalidate the path, the data is well refreshed, the client component get it, but I have to set the state in a useEffect to get thinks work, is it normal?
I have a Client component that get props from Layout server component (a chat sidebar).
When a new conversation is created, I revalidate the path, the data is well refreshed, the client component get it, but I have to set the state in a useEffect to get thinks work, is it normal?
export default function ConversationsNavList({
conversations,
}: {
conversations: Conversation[];
}) {
const pathname = useSelectedLayoutSegment();
const [conv, setConv] = useState<Conversation[]>(conversations);
const [open, setOpen] = useState(false);
const [selectedConv, setSelectedConv] = useState<Conversation | null>(null);
const router = useRouter();
const { toast } = useToast();
const [optimisticConversations, deleteOptimisticConversation] = useOptimistic(
conv,
(state, convId) => state.filter((conv) => conv.id_conversation !== convId)
)
// This is necesary because if conversations is updated by the server the state won't be
useEffect(() => setConv(conversations), [conversations])
}7 Replies
the RevalidatePath really rerenders the whole component but it doesnt unmount any existing components. You'd have to "listen" to changes in the props and choose to either override current state or skip the changes in the props.
@Spectacled bear Hey,
I have a Client component that get props from Layout server component (a chat sidebar).
When a new conversation is created, I revalidate the path, the data is well refreshed, the client component get it, but I have to set the state in a useEffect to get thinks work, is it normal?
ts
export default function ConversationsNavList({
conversations,
}: {
conversations: Conversation[];
}) {
const pathname = useSelectedLayoutSegment();
const [conv, setConv] = useState<Conversation[]>(conversations);
const [open, setOpen] = useState(false);
const [selectedConv, setSelectedConv] = useState<Conversation | null>(null);
const router = useRouter();
const { toast } = useToast();
const [optimisticConversations, deleteOptimisticConversation] = useOptimistic(
conv,
(state, convId) => state.filter((conv) => conv.id_conversation !== convId)
)
// This is necesary because if conversations is updated by the server the state won't be
useEffect(() => setConv(conversations), [conversations])
}
use react keys:
generate a key so that the same
// before
<ConversationsNavList
conversations={conversations}
/>
// after
<ConversationsNavList
conversations={conversations}
key={...}
/>generate a key so that the same
conversations get the same key, but different conversations will return different key. depending on your logic a key={conversations.length} might already suffice.@ᴉuɐpɹɐɐ the RevalidatePath really rerenders the whole component but it doesnt unmount any existing components. You'd have to "listen" to changes in the props and choose to either override current state or skip the changes in the props.
Spectacled bearOP
The weird thing is that I do navigate to the new route (from
/conversations/new to /conversations/:id) so I was expecting the client component in /conversations layout to remount@joulev use react keys:
tsx
// before
<ConversationsNavList
conversations={conversations}
/>
// after
<ConversationsNavList
conversations={conversations}
key={...}
/>
generate a key so that the same `conversations` get the same `key`, but different `conversations` will return different `key`. depending on your logic a `key={conversations.length}` might already suffice.
Spectacled bearOP
Seems a nice solution! Will try it out
Didn't work, sadly
@ᴉuɐpɹɐɐ the RevalidatePath really rerenders the whole component but it doesnt unmount any existing components. You'd have to "listen" to changes in the props and choose to either override current state or skip the changes in the props.
Spectacled bearOP
Isn't it weird for a react component to not rerender when props changes?
@Spectacled bear Didn't work, sadly
Hmm seems like you are facing the same issue as this person https://nextjs-forum.com/post/1240503542591258674. I discussed a few more points there that may also be applicable to your case