Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
579 views
in Technique[技术] by (71.8m points)

reactjs - Why is my cached state undefined on mutate in SWR?

I have a component that gets the data for a subreddit with posts and every post has a vote:

const subUrl = `/api/subreddit/findSubreddit?name=${sub}`;

  const { data: fullSub, error } = useSWR(subUrl, fetchData, {
    initialData: props.fullSub, //comes from next.js getServerSideProps
  });

This works perfectly fine and it renders everything on the screen. But on my subredditPost component (I render a subredditPost for each post) I have this onClick function when I click the upvote button:

const upvotePost = async (postid, fullSub, subUrl) => {
  console.log("the sub variable is: ", subUrl); //same url as in the main component
  mutate(
    subUrl,
    async (data) => {
    // this is undefined when I hit on the upvote button
    // Expected: The current state of swr with the key of subUrl
      console.log("cached value: ", data);
      return {
        ...data,
        posts: data.posts.map((post) => {
          if (post.id === postid) {
            return {
              ...post,
              votes: [...post.votes, { voteType: "UPVOTE" }],
            };
          } else {
            return post;
          }
        }),
      };
    },
    false
  );
  const res = await fetch("/api/post/upvote", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ postId: postid }),
  });
  mutate(subUrl);
};

It always is undefined in the console.log on the code above. So I get an error and nothing renders on the page anymore. What am I doing wrong? I read it can't get the cache if I use a different key, but I'm using the same key. I pass the subUrl from my main component (where I fetch the subreddit) to the post component (where I click the upvote button). So it is exactly the same.

Why do I get undefined?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I was able to solve this issue by providing a default value to mutate like this:

mutate(
    sub,
    async (data = fullSub) => {
      console.log("cached value: ", data);
      return {
        ...data,
        posts: data.posts.map((post) => {
          if (post.id === postid) {
            return {
              ...post,
              votes: [...post.votes, { voteType: "UPVOTE" }],
            };
          } else {
            return post;
          }
        }),
      };
    },
    false
  );

So give the async function a default value if it's undefined: async (data = fullSub)

That fixes it but it's still not clear why it's undefined? Maybe somebody can answer this. I will leave this open for now, after a while if nobody has a better answer I will mark mine.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...