swr
swr copied to clipboard
The type and runtime behavior of `mutate/trigger` fn are mismatched
Problem
The runtime behavior of mutate/trigger
is complex and the current type does not correctly match the actual behavior.
mutate('/key', fetcher, { populateCache: true, revalidate: true }) // -> return revalidation result
mutate('/key', fetcher, { populateCache: true, revalidate: false }) // -> return fetcher result
mutate('/key', fetcher, { populateCache: () => Data, revalidate: true }) // -> return revalidation result
mutate('/key', fetcher, { populateCache: () => Data, revalidate: false }) // -> return Data
mutate('/key', fetcher, { populateCache: false, revalidate: true }) // -> return fetcher result
mutate('/key', fetcher, { populateCache: false, revalidate: false }) // -> return fetcher result
related issues
#2647 #2661
I also got this issue. @promer94 What do you think should be the correct behavior of mutate/trigger? I suggest it always return the fetcher's result, undefined if fetcher isn't provided, because sometimes we have to mutate local data in a chain.
For example, in an IM app, when user sends a new message to a conversation, we need to insert this message to local message list and update the corresponding conversation's latest message. I'm not sure if the following is the best practice, anyway it's our current way:
export function useSendMessage(conversationId:string, message: string) {
const insertMessage: () => Promise<Message> = () => {
// promise that insert message through a post request
}
const {trigger: triggerMessages} = useSWRMutation<Message[]>(MESSAGGS_KEY_OF(conversationId), post, {
populateCache(result, currentData) => {
// the first issue here, type mismatched,
// mutate/trigger expects the fetcher's response type the same as the existing data,
// which is not always true
const insertedMessage = result as unknown as Message
return [message, ...currentData]
}
})
return useSWRMutation<Conversation[]>(CONVERSATIONS_KEY, () => triggerMessages(), {
populacateCache(result, currentData) => {
// the second issue here, the triggerMessages() sometimes returns Message,
// sometimes returns Message[], depending on values of populateCache and revalidate
const insertedMessage = result[0]
// in some other case, it should be
// const insertedMessage = result
// update conversations then return
}
})
}