Advanced
Customizing the theme components
The components used by the Twitter theme allow some simple customization options for common use cases. However you can also have full control over the tweet by building your own Tweet
component with the components and features of the theme that you would like to use.
For example, you can build your own tweet component but without the reply button like so:
import type { Tweet } from 'react-tweet/api'
import {
type TwitterComponents,
TweetContainer,
TweetHeader,
TweetInReplyTo,
TweetBody,
TweetMedia,
TweetInfo,
TweetActions,
QuotedTweet,
enrichTweet,
} from 'react-tweet'
type Props = {
tweet: Tweet
components?: TwitterComponents
}
export const MyTweet = ({ tweet: t, components }: Props) => {
const tweet = enrichTweet(t)
return (
<TweetContainer>
<TweetHeader tweet={tweet} components={components} />
{tweet.in_reply_to_status_id_str && <TweetInReplyTo tweet={tweet} />}
<TweetBody tweet={tweet} />
{tweet.mediaDetails?.length ? (
<TweetMedia tweet={tweet} components={components} />
) : null}
{tweet.quoted_tweet && <QuotedTweet tweet={tweet.quoted_tweet} />}
<TweetInfo tweet={tweet} />
<TweetActions tweet={tweet} />
{/* We're not including the `TweetReplies` component that adds the reply button */}
</TweetContainer>
)
}
Then, you can build your own Tweet
component that uses the MyTweet
component:
import { Suspense } from 'react'
import { getTweet } from 'react-tweet/api'
import { type TweetProps, TweetNotFound, TweetSkeleton } from 'react-tweet'
import { MyTweet } from './my-tweet'
const TweetContent = async ({ id, components, onError }: TweetProps) => {
const tweet = id
? await getTweet(id).catch((err) => {
if (onError) {
onError(err)
} else {
console.error(err)
}
})
: undefined
if (!tweet) {
const NotFound = components?.TweetNotFound || TweetNotFound
return <NotFound />
}
return <MyTweet tweet={tweet} components={components} />
}
export const Tweet = ({
fallback = <TweetSkeleton />,
...props
}: TweetProps) => (
<Suspense fallback={fallback}>
{/* @ts-ignore: Async components are valid in the app directory */}
<TweetContent {...props} />
</Suspense>
)
The Tweet
component uses Suspense
to progressively load the tweet (non-blocking rendering) and to opt-in into streaming if your framework supports it, like Next.js.
TweetContent
is an async component that fetches the tweet and passes it to MyTweet
. async
only works for React Server Components (RSC) (opens in a new tab) so if your framework does not support RSC you can use SWR (opens in a new tab) instead:
'use client'
import {
type TweetProps,
EmbeddedTweet,
TweetNotFound,
TweetSkeleton,
useTweet,
} from 'react-tweet'
export const Tweet = ({
id,
apiUrl,
fallback = <TweetSkeleton />,
components,
onError,
}: TweetProps) => {
const { data, error, isLoading } = useTweet(id, apiUrl)
if (isLoading) return fallback
if (error || !data) {
const NotFound = components?.TweetNotFound || TweetNotFound
return <NotFound error={onError ? onError(error) : error} />
}
return <EmbeddedTweet tweet={data} components={components} />
}