vercel / react-tweet

Embed tweets in your React application.

Home Page:https://react-tweet.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tweet Not Found

JamesSingleton opened this issue · comments

I know there is already another issue for this #134 but they closed it without an actual resolution from the library itself. I can get the tweet to load on localhost:3000 just fine
Screenshot 2023-09-04 at 12 03 45 PM

However, when I am previewing it through a deployment branch, it just returns Tweet not found

Screenshot 2023-09-04 at 12 02 55 PM

I get no errors in my Vercel logs at all and nothing in the console and nothing in the network tab. This is currently stopping me from publishing some changes to my website.

So I decided to just push my changes to production and just tell my authors to not include tweets for the time being... However, I can now see errors in Vercel but all it is saying is

Error: Failed to get tweet data for tweet ID: 1556693648762437637
    at getTweets (/var/task/.next/server/pages/[slug].js:676:15)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async getStaticProps$1 (/var/task/.next/server/pages/[slug].js:156:31)
    at async /var/task/node_modules/@sentry/nextjs/cjs/server/utils/wrapperUtils.js:38:14 {
  page: '/vmi-gets-a-commitment-from-2023-3-star-cb-davion-corpening'
}
RequestId: 0581bce3-020b-4225-902f-5ad7b122e9b2 Error: Runtime exited with error: exit status 1
Runtime.ExitError

However, the tweet does exist https://twitter.com/IamTheKeyDC/status/1556693648762437637

I am currently experiencing the same issue. Could it be related to the recent update to version 3.1.1?
I also noticed that we can view the tweet locally but not in production.

I am currently experiencing the same issue. Could it be related to the recent update to version 3.1.1?
I also noticed that we can view the tweet locally but not in production.

Yea not entirely sure, but I even tried with the apiUrl route that they mention but shouldn't need to use if I am in Next.js and then locally my tweets won't load. What's odd is I use this component in my Sanity studio to preview tweets and it works just fine... Not sure why on my website it doesn't.

Same here makes the package unusable for me

Same here makes the package unusable for me

Yea hopefully someone from Vercel can take a look or give some guidance. I guess looking at the documentation for Next, I should be manually fetching this data since I generate static params for my articles?

Same here makes the package unusable for me

Yea hopefully someone from Vercel can take a look or give some guidance. I guess looking at the documentation for Next, I should be manually fetching this data since I generate static params for my articles?

I am manually fetching the data through a TRPC call and it still doesn't work

I was looking at how @steven-tey was doing it in Dub https://github.com/steven-tey/dub/tree/main and the tweets are clearly loading for him and he is using getTweet. 🤔

Well I tried and I get the following in Vercel but it still works locally 🙃 :

Screenshot 2023-09-11 at 9 46 50 PM

@lfades any guidance here for us? It's currently blocking a couple of us from actually being able to use this library.

I'm experiencing the same issue at the moment

I'm experiencing the same issue at the moment

Yea I even tried how a couple of Vercel engineers use react-tweet and either end up my pages with tweets just completely 404ing or in the same position that I am in right now.

From some googling it seems to be Twitter blocking AWS, what I don't understand is how others have it working

Not an ideal solution but I got it working using a proxy and recreating the function:

export async function getTweet(id: string, fetchOptions?: RequestInit) {
  if (id.length > 40 || !TWEET_ID.test(id)) {
    throw new Error(`Invalid tweet id: ${id}`);
  }

  const url = new URL(`${SYNDICATION_URL}/tweet-result`);

  url.searchParams.set("id", id);
  url.searchParams.set("lang", "en");
  url.searchParams.set(
    "features",
    [
      "tfw_timeline_list:",
      "tfw_follower_count_sunset:true",
      "tfw_tweet_edit_backend:on",
      "tfw_refsrc_session:on",
      "tfw_fosnr_soft_interventions_enabled:on",
      "tfw_show_birdwatch_pivots_enabled:on",
      "tfw_show_business_verified_badge:on",
      "tfw_duplicate_scribes_to_settings:on",
      "tfw_use_profile_image_shape_enabled:on",
      "tfw_show_blue_verified_badge:on",
      "tfw_legacy_timeline_sunset:true",
      "tfw_show_gov_verified_badge:on",
      "tfw_show_business_affiliate_badge:on",
      "tfw_tweet_edit_frontend:on",
    ].join(";")
  );
  url.searchParams.set("token", getToken(id));

  const headers = {
    "User-Agent":
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0",
    Accept: "*/*",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br",
    Origin: "https://platform.twitter.com",
    Connection: "keep-alive",
    Referer: "https://platform.twitter.com/",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "cross-site",
    Pragma: "no-cache",
    "Cache-Control": "no-cache",
    TE: "trailers",
  };

  const proxyAgent = new HttpsProxyAgent(
    proxy_url
  );

  const rep = await axios.get<Tweet>(url.toString(), {
    headers,
    httpsAgent: proxyAgent,
  });

  return rep.data;
}

@lleewwiiss I wonder if that is why @steven-tey and other Vercel employees cache the tweet results in upstash/redis?

@lleewwiiss I wonder if that is why @steven-tey and other Vercel employees cache the tweet results in upstash/redis?

Maybe but in the example app if you enter a random tweet ID that I assume isn't cached it still seems to work, It might also be a Cors thing but I'll just use a proxy until this is resolved or we have some guidance.

Yeah I'm not sure anymore either as I've tried the api route they have as an example in this repo and I still get that it's not found.

I'm experiencing the same issue at the moment

Surprisingly today, it worked on my website!! Nothing changed in my code...

I'm experiencing the same issue at the moment

Surprisingly today, it worked on my website!! Nothing changed in my code...

Yeah I just checked my website and it’s working as well now… I made no changes to the code.

Me as well with no proxy

  1. This is because X is blocking those requests from common hosting providers so you want to get data locally or from the browser in a panel and then save that data in some sort of cache.

  2. The solution is to use Manual Data Fetching locally on build time when you can access X API with getTweet(tweetId) and getTweet(tweetId). This can be done on localhost or in browser using user IP address.

  3. When you get that data you want to cache it. I recommend Vercel/KV or Redis. I implemented it and I'm very happy how it's working. There was only one issue when I was using Next.js App Router with static pages - check next point.

  4. When using Next.js App Router with SSG/ISR (force-static) then the KV get call kv.get(tweetId) won't work when you build it or deploy it to Vercel. The issue you will see would be:

Page changed from static to dynamic at runtime /ai/wordtune, reason: no-store fetch https://electric-XX-XXX.kv.vercel-storage.com /ai/[tool] see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error

This is happening when you pnpm build and pnpm start locally or when you build and deploy on Vercel.

The solution to fix KV call on static pages is to refactor it to use Vercel KV REST API with caching options.

Example static friendly KV get call example:

// fetching tweets and caching in KV
  const TweetIds = ["1705688070941520030","1705162823003734354"]
  const tweets: Tweet[] = [];
  if (TweetIds) {
    for (const tweetId of TweetIds) {
      let kvTweet: Tweet | undefined | null = null;

      // check kv cache first
      try {
        const res = await fetch(
          `${process.env.KV_REST_API_URL}/get/tweet:${tweetId}`,
          {
            headers: {
              Authorization: `Bearer ${process.env.KV_REST_API_TOKEN}`,
            },
            cache: "force-cache",
            next: {
              tags: [`tweets`],
            },
          } as any
        );
        const json = await res.json();
        kvTweet = JSON.parse(json.result) as Tweet;
      } catch (err) {
        console.log(err);
        console.log("Error fetching tweet from KV");
      }

      if (kvTweet) {
        tweets.push(kvTweet);
      } else {
        // fetch tweet
        try {
          const tweet = await getTweet(tweetId);
          if (tweet) {
            tweets.push(tweet);
            // cache tweet in KV
            await kv.set(`tweet:${tweetId}`, tweet);
          }
        } catch (e) {
          console.warn(`Error fetching tweet ${tweetId} from X`);
          console.warn(e);
        }
      }
    }
  }

I had almost the same experience. https://twitter.com/t6adev/status/1746699829336780921

This is because X is blocking those requests from common hosting providers

I'm not sure about it. But I can say something We need to take a workaround against Twitter's behavior.

I am back to getting this error in production again... It says the tweet was not found...

Screenshot 2024-02-24 at 9 28 02 AM

However, in my CMS (Sanity) it shows it just fine

Screenshot 2024-02-24 at 9 28 40 AM

They are both on the same domain and my sanity studio is built directly into my Next.js application. What is weird is there was a query param of like ?s=20 or something like that. I guess it didn't like that?

I got the issue resolved!!!.

I have an issue in development.

image

As you can see, the tweet is working fine is production but in development it says tweet not found or something like giving an network error:
image

Solution

The solution to this problem is using 'use client' in development and remove once you go into the production. As you know that the code is working in production but causing problems in development which causes problems in development.

'use client' // Remove this in production to get advantage of server components 

import { Tweet } from 'react-tweet'
 
export default function Page() {
  return <Tweet id="1628832338187636740" />
}

Result
image