Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CH17: useOptimistic hook not working as expected #13

Open
cherishh opened this issue Feb 18, 2024 · 1 comment
Open

CH17: useOptimistic hook not working as expected #13

cherishh opened this issue Feb 18, 2024 · 1 comment

Comments

@cherishh
Copy link

cherishh commented Feb 18, 2024

Hi, I've been following this course up to Chapter 17, which covers "Implementing an Optimistic UI with the React useOptimistic Hook in Next.js." I've run into an issue where, after triggering addOptimisticTweet (from the useOptimistic hook), and before the backend call is completed, the Tweets component renders twice unexpectedly. The first render correctly updates the like count, e.g., from 0 to 1. However, the second render, which shouldn't happen, resets the like count from 1 back to 0, resulting the useOptimistic hook ineffective.

Issue:
image
Untitled_ Feb 18, 2024 2_38 PM (1)

Tweets.tsx

export default function Tweets({ tweets, user }: { tweets: TweetWithAuthor[]; user: User }) {
  const router = useRouter()
  const supabase = createClientComponentClient<Database>();
  const [optimisticTweets, addOptimisticTweet] = useOptimistic<TweetWithAuthor[], TweetWithAuthor>(
    tweets,
    (currOptimisticTweets, newTweet) => {
      const newOptimisticTweets = [...currOptimisticTweets];
      const index = newOptimisticTweets.findIndex((t) => t.id === newTweet.id);
      newOptimisticTweets[index] = newTweet;
      return newOptimisticTweets;
    }
  );

  useEffect(() => {
    const channel = supabase.channel('realtime tweets').on('postgres_changes', {
      event: '*',
      schema: 'public',
      table: 'tweets'
    }, (payload) => {
      router.refresh()
    }).subscribe(); 

    return () => {
      channel.unsubscribe();
    }
  }, [supabase, router]);

  console.log(JSON.parse(JSON.stringify(optimisticTweets[0])), 'render');

  return optimisticTweets.map((tweet) => (
    <div key={tweet.id} className='m-8'>
      <p>{tweet.author.username}</p>
      <p>{tweet.title}</p>
      <LikeButton tweet={tweet} addOptimisticTweet={addOptimisticTweet} user={user} />
    </div>
  ));
}

LikeButton.tsx

export default function LikeButton({tweet, addOptimisticTweet, user}: { tweet: TweetWithAuthor, addOptimisticTweet: (newTweet: TweetWithAuthor) => void, user: User }) {
  const router = useRouter();

  const handleClick = async () => {
    const supabase = createClientComponentClient<Database>();
    // const { data: { user } } = await supabase.auth.getUser();
    if (!user) return;
    if (tweet.user_has_liked_tweet) {
      startTransition(() => {
        addOptimisticTweet({
          ...tweet,
          likes: tweet.likes - 1,
          user_has_liked_tweet: false,
        })
      })
      
      await supabase.from('likes').delete().match({'tweet_id': tweet.id, 'user_id': user.id });
      router.refresh(); 
    } else {
      startTransition(() => {
        addOptimisticTweet({
          ...tweet,
          likes: tweet.likes + 1,
          user_has_liked_tweet: true,
        })
      })
      await supabase.from('likes').insert({ tweet_id: tweet.id, user_id: user.id });
      router.refresh();
    }
  }

  return (
    <div>
      <button onClick={handleClick}>{tweet.likes} likes</button>
    </div>
  )
}

Here's my full code: https://github.com/cherishh/clone-twitter
One note, though: I'm using a traditional username/password authentication method instead of OAuth. However, I don't believe this is relevant to the issue at hand.

Any assistance would be appreciated.

@cherishh
Copy link
Author

UPDATE
Turns out it's a nextjs bug. I was originally using 14.1.0 and this problem occurs. When I change it to 13.4.7 which this tutorial uses, everything is fine.

But now I got another question: I've pulled this repository and tried again with logging the same thing. Amazingly, Tweets also renders twice, but the actual page doesn't gets updated. How does this happen??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant