Skip to content

Sideeffects on local bound mutate after changing key #1732

@samedii

Description

@samedii

Bug report

Description / Observed Behavior

If I understand correctly, the mutate method for the old key changes the new object that has a different key. The key has changed while a request is made to the server. When getting the response from the server I want to update the cache with the result from the server but the local bound mutate has changed behaviour.

I am able to get around this by keeping track of the original key and using the global mutate which makes me think that my code might be working correctly and this could be a bug.

I've tried searching for this issue but I may have missed some important keyword that I was unable to figure out.

Expected Behavior

I would expect swr to give me a function that I can use even after the key that was used to create it has changed. It felt like a very unexpected side effect.

Repro Steps / Code Example

The global solution is implemented below. Remove the comment to change to the local bound method.

import { useAuthorizedFetcher } from "./useAuthorizedFetcher";
import useBackend from "./useBackend";
import { useSWRConfig } from "swr";

const useImage = (imageId, options) => {
  const { mutate } = useSWRConfig();
  const authorizedFetcher = useAuthorizedFetcher();
  const image = useBackend(imageId ? `/images/${imageId}` : null, { options });
  // const mutate = (key, value, revalidate) => image.mutate(value, revalidate);

  const api = ((isLoading, data, key, mutate) => {
    const createAnnotation = (annotationType) => {
      if (!isLoading && data.hot_storage) {
        mutate(
          key,
          {
            ...data,
            annotations: [
              ...(data.annotations ?? []),
              {
                id: "added",
                type: annotationType,
              },
            ],
          },
          false
        );
        return authorizedFetcher(`/images/${imageId}/annotations`, {
          method: "POST",
          body: { type: annotationType },
        }).then(
          (data) => mutate(key, data, false)
        );
      } else {
        return Promise.resolve(image);
      }
    };

    // ...

    return {
      createAnnotation,
      // ...
    };
  })(image.isLoading, image.data, image.key, mutate);

  return {
    ...image,
    ...api,
  };
};

export default useImage;

Additional Context

Using SWR version 1.0.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions