Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Is there a way to use this module with nextjs on a component level? #9

Closed
HynekS opened this issue Feb 21, 2021 · 6 comments
Closed

Comments

@HynekS
Copy link
Contributor

HynekS commented Feb 21, 2021

Is there a way to use this module with nextjs app, but not as a singular tweet page (as shown in demo), but as a nested component? Use case: blog post including one or multiple tweets, probably statically generated. I am currently using the twitter api and recreating the tweets from responses, but that is quite cumbersome (registration needed, CORS issues). I made an attempt to use the example code:

import React from 'react'
import { fetchTweetAst } from 'static-tweets'
import { Tweet } from 'react-static-tweets'

const tweetId = '1358199505280262150'

export const getStaticProps = async () => {
  try {
    const tweetAst = await fetchTweetAst(tweetId)

    return {
      props: {
        tweetId,
        tweetAst
      },
      revalidate: 10
    }
  } catch (err) {
    console.error('error fetching tweet info', err)

    throw err
  }
}

export default function Example({ tweetId, tweetAst }) {
  return <Tweet id={tweetId} ast={tweetAst} />
}

but I haven't found a way to pass the hardcoded tweetId variable as a dynamic argument on getStaticProps. Taking a look into nextjs docs, there is optional context parameter that can be used in getStaticProps, but it is limited to path params and a bunch of meta stuff. Is this currently possible considering the way getStaticProps works?

@transitive-bullshit
Copy link
Owner

@HynekS see the other page in the example which takes in a dynamic tweetId https://github.com/transitive-bullshit/react-static-tweets/blob/master/example/pages/%5BtweetId%5D.tsx

@transitive-bullshit
Copy link
Owner

Also note that you can totally render tweets entirely client-side. Pre-loading their AST on the server-side as part of the static props is an optimization.

@HynekS
Copy link
Contributor Author

HynekS commented Feb 22, 2021

Thank you, Travis. I've seen the other page example, but it still depends on the tweeId being passed via slug ([tweetId].tsx, which is later being used as context.params.tweetId). Thus, I can't see a way to use it on a nested component level (which has no slug).

But this is almost certainly not an issue of your module, but rather a limitation of Next.js.

I will probably try my luck with the client side rendering. Also, using Sanity.io as a CMS, I could create a custom input, that would implement static-tweets to get the tweet AST in the CMS (where delay or layout shift is not an issue), save a tweet as AST and then use it for SSR or SSG on the frontend.

@transitive-bullshit
Copy link
Owner

transitive-bullshit commented Feb 23, 2021

There are a few workarounds.

  1. Client-side rendering and fetching the tweet AST on-the-fly.
  2. If you have a way of extracting all the tweet IDs a page will use from your CMS, you can pre-fetch the ASTs server-side.
  3. @rauchg has a great example of how to do this automatically via a cool trick where you render the page server-side within a temporary context, while tracking the tweets that would be rendered. This is a bit more advanced, but you could definitely integrate this approach with react-static-tweets — https://github.com/rauchg/blog/blob/a1192e9bb804290c0b3f878853aa094412ba1a3d/lib/get-tweets.js

@HynekS
Copy link
Contributor Author

HynekS commented Feb 28, 2021

Thank you for the link to Guillermos blog, it helped me significantly. I realized I already have all the data I need in getStaticProps on the page (or post, respectively) level. So, considering the data are coming form Sanity.io api, I can do e. g.:

// pages/post/[slug].js

export const getStaticProps = async function (context) {
  const post = await client.fetch(query, { slug: context.params.slug })

  const withTweetAst = await Promise.all(
    post.body.map(async block => {
      if (block._type !== "twitter") {
        return block
      } else {
        try {
          const tweetAst = await fetchTweetAst(block.id)
          return {
            ...block,
            ast: tweetAst,
          }
        } catch (err) {
          console.error("error fetching tweet info", err)
          return {
            ...block,
            ast: null,
          }
        }
      }
    }),
  )

  return {
    props: {
      post: {
        ...post,
        body: withTweetAst,
      },
    },
  }
}

Then, I can use Tweet component to render, because I already have ast and id props available.

Since this issue has nothing to do with your lib, but rather my lack of experience with Next.js, I am closing it. Thank you!

@HynekS HynekS closed this as completed Feb 28, 2021
@transitive-bullshit
Copy link
Owner

Looks great.

One suggestion would be to use https://github.com/sindresorhus/p-map instead of Promise.all since it allows you to control the concurrency.

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

No branches or pull requests

2 participants