Reputation: 278
I have a page that uses the getStaticProps
function. The function loads a list of objects that each hold three things: the title of a book, the author of a book, and then a list of characters in the book. The page then maps each of these objects to a component that puts them in a pretty pill.
The component takes the title and author and embeds it into its HTML code. However, the one complexity is the component also uses a useEffect()
hook to randomly select 1 character within the character list provided as a prop and then displays them as part of the component HTML. Since it is useEffect()
, this does not happen at build time. The reason I want it to occur when the user requests the page is that each user should see a different randomly selected character (i.e., although everything else on the page is the same for all users, I want the character to be randomly selected).
My question is, can getStaticProps
work here? Does it build out the HTML as best it can and then when the user requests the page, the character list data is already provided? Or because it uses useEffect()
, the component will have to re-request the data from the backend? I want to limit backend requests because the data is stored in AirTable and that only allows 5 calls per second.
index.jsx
:
const Home = (props) => {
return (
<div className="flex min-h-screen">
<main className="relative mx-5 mt-16">
{props.response.map((bookData) => (
<BookPill
bookTitle={bookData['Book Title']}
bookAuthor={bookData['Book Author']}
bookCharacters={bookData['Characters']}
/>
))}
</main>
</div>
)
}
export default Home
export async function getStaticProps(context) {
try {
const response = await getBookData()
return {
props: {
response,
},
revalidate: 5,
}
} catch (error) {
return {
props: {
err: 'Something went wrong 😕',
},
}
}
}
BookPill.jsx
:
const BookPill = ({
bookTitle,
bookAuthor,
bookCharacters,
}: PropsType) => {
const [randomCharacter, setRandomCharacter] = useState('')
useEffect(() => {
const random_character =
bookCharacters[Math.floor(Math.random() * bookCharacters.length)]
setRandomCharacter(random_character)
}, [])
return (
<div className="my-2 grid grid-cols-1">
<div className="px-5 text-center">
<p className="mb-4">{bookTitle}</p>
<p className="text-sm">{bookAuthor}</p>
</div>
<div className="flex items-center justify-center md:col-span-1">
<div className="rounded-3xl">
{randomCharacter}
</div>
</div>
</div>
)
}
export default BookPill
Upvotes: 1
Views: 268
Reputation: 50308
To summarize what was discussed in the comments:
Because you're using getStaticProps
with revalidate: 5
, the data will only be fetched on the server, at most every 5 seconds. The data fetched inside getStaticProps
is then passed to the HTML generated for the page - you can see the props returned from getStaticProps
in the __NEXT_DATA__
script in your HTML.
When the page gets rendered on the browser, the useEffect
is triggered and will use that data. No additional requests occur on the client-side.
Upvotes: 1