react-tweet, react-twitter-embed, and react-twitter-widgets are npm packages designed to embed Twitter (now X) content—such as individual tweets or timelines—into React applications. They abstract the complexity of integrating Twitter's official widget.js script, but differ significantly in implementation strategy, reliability, and modern React compatibility. react-tweet uses a more isolated, component-based approach with built-in loading states and SSR support, while react-twitter-embed and react-twitter-widgets rely on injecting and managing Twitter's global script directly in the DOM, leading to potential issues in secure or server-rendered environments.
Embedding tweets or timelines in a React application seems straightforward—until you consider performance, loading behavior, customization, and maintenance. The three main npm packages for this task—react-tweet, react-twitter-embed, and react-twitter-widgets—each take a different technical approach. Let’s compare them head-to-head from an architect’s perspective.
react-tweet uses Twitter’s official @twitter/embed SDK under the hood, but wraps it in a modern, React-friendly component that avoids global script pollution. It renders tweets using Twitter’s native embed logic but isolates it within a controlled lifecycle. No external <script> tags are injected into the document head.
// react-tweet
import { Tweet } from 'react-tweet';
function App() {
return <Tweet id="1587234567890123456" />;
}
react-twitter-embed dynamically injects Twitter’s widget.js script into the DOM when a component mounts. It then uses window.twttr.widgets.createTweet() to render the tweet inside a container div. This means it relies on mutating the global scope and assumes the script is loaded before rendering.
// react-twitter-embed
import { TwitterTweetEmbed } from 'react-twitter-embed';
function App() {
return <TwitterTweetEmbed tweetId="1587234567890123456" />;
}
react-twitter-widgets also depends on loading Twitter’s widget.js, but provides a thin wrapper around the official twttr.widgets API. Like react-twitter-embed, it requires the script to be present and uses imperative DOM manipulation after mount.
// react-twitter-widgets
import { Tweet } from 'react-twitter-widgets';
function App() {
return <Tweet tweetId="1587234567890123456" />;
}
⚠️ Important: Both
react-twitter-embedandreact-twitter-widgetscan cause issues in environments where global scripts are restricted (e.g., strict CSP, server-side rendering, or micro-frontend sandboxes).react-tweetavoids this by encapsulating the embed logic.
react-tweet ships with built-in skeleton placeholders that mimic the tweet’s layout while content loads. This prevents layout shifts and gives users immediate visual feedback.
// react-tweet automatically shows a skeleton until the tweet loads
<Tweet id="1587234567890123456" />
react-twitter-embed offers no built-in loading UI. The container remains empty until Twitter’s script loads and renders the iframe, which can cause noticeable content jumps or blank spaces.
// react-twitter-embed: blank div until script runs
<TwitterTweetEmbed tweetId="1587234567890123456" />
react-twitter-widgets behaves similarly—no placeholder, no loading state management. You must implement your own spinner or skeleton if needed.
// react-twitter-widgets: same blank-container issue
<Tweet tweetId="1587234567890123456" />
react-tweet is SSR-safe. It renders a static placeholder on the server and hydrates only on the client. This makes it compatible with Next.js, Remix, and other SSR frameworks without extra work.
react-twitter-embed is not SSR-safe. It tries to access window and document during render, which will crash in Node.js environments unless wrapped in dynamic imports or conditional checks.
// Workaround needed for SSR
import dynamic from 'next/dynamic';
const TwitterTweetEmbed = dynamic(() => import('react-twitter-embed').then(mod => mod.TwitterTweetEmbed), { ssr: false });
react-twitter-widgets has the same SSR limitation—it assumes browser globals exist at render time.
react-tweet supports light/dark themes out of the box via a theme prop. It also respects system preference if none is specified.
<Tweet id="1587234567890123456" theme="dark" />
react-twitter-embed allows passing options to Twitter’s embed API, including theme, but you must structure them as an object:
<TwitterTweetEmbed tweetId="1587234567890123456" options={{ theme: 'dark' }} />
react-twitter-widgets also accepts an options prop that maps directly to Twitter’s widget parameters:
<Tweet tweetId="1587234567890123456" options={{ theme: 'dark' }} />
However, only react-tweet handles theme switching without re-injecting scripts—the others may trigger full re-renders or flicker when props change.
react-tweet properly responds to prop changes (e.g., switching tweet IDs). It cleans up the previous embed and initializes a new one without leaking resources.
react-twitter-embed and react-twitter-widgets do not reliably handle dynamic tweet ID changes. Because they rely on imperative DOM mutation tied to a single mount, updating the tweetId often fails to re-render unless you force a key reset:
// Common workaround for react-twitter-embed
<TwitterTweetEmbed
key={currentTweetId}
tweetId={currentTweetId}
/>
This is a significant footgun in data-driven UIs (e.g., carousels, feeds).
As of 2024:
react-tweet is actively maintained, follows modern React patterns (hooks, suspense-ready), and aligns with Twitter/X’s current embed guidelines.react-twitter-embed has not seen meaningful updates since 2022. Its GitHub repo shows unresolved issues related to hydration and script conflicts.react-twitter-widgets appears abandoned; its last publish was years ago, and it lacks TypeScript definitions or modern React compatibility fixes.🚫 Neither
react-twitter-embednorreact-twitter-widgetsshould be used in new projects due to maintenance risks and architectural limitations.
All three packages can display a tweet in a simple Create React App with client-side rendering. But real applications need:
Only react-tweet meets these requirements out of the box.
| Feature | react-tweet | react-twitter-embed | react-twitter-widgets |
|---|---|---|---|
| SSR Support | ✅ Yes | ❌ No (requires workaround) | ❌ No (requires workaround) |
| Built-in Skeleton | ✅ Yes | ❌ No | ❌ No |
| Dynamic ID Updates | ✅ Safe | ⚠️ Requires key hack | ⚠️ Requires key hack |
| No Global Script Leak | ✅ Yes | ❌ Injects widget.js | ❌ Injects widget.js |
| Active Maintenance | ✅ Yes | ❌ Stale | ❌ Abandoned |
| Theme Support | ✅ Simple prop | ✅ Via options | ✅ Via options |
For any professional React application—especially those using SSR, strict security policies, or dynamic content—react-tweet is the only viable choice. The other two packages introduce technical debt through global side effects, poor lifecycle hygiene, and lack of maintenance. While they might seem simpler at first glance, their hidden costs in debugging, workarounds, and fragility far outweigh any perceived ease of use.
Choose react-tweet for any production React application, especially if you use SSR (Next.js, Remix), enforce strict Content Security Policies, or need reliable dynamic tweet rendering. It provides built-in skeletons, proper cleanup, theme support, and avoids global script pollution—making it the only future-proof option among the three.
Avoid react-twitter-embed in new projects. While it works in simple client-side apps, it injects scripts globally, breaks during SSR, doesn’t handle dynamic tweet ID changes safely, and hasn’t been actively maintained. Only consider it for legacy codebases where migration isn’t feasible.
Do not use react-twitter-widgets in new development. It is effectively abandoned, lacks TypeScript support, fails in SSR contexts, and offers no advantages over alternatives. Its reliance on imperative DOM manipulation makes it incompatible with modern React best practices.
react-tweet allows you to embed tweets in your React application when using Next.js, Vite, and more.
For documentation visit react-tweet.vercel.app.
Visit our contributing docs.