I'm fetching WordPress posts asynchronously via getStaticProps()...
export async function getStaticProps({ params, preview = false, previewData }) {
const data = await getPostsByCategory(params.slug, preview, previewData)
return {
props: {
preview,
posts: data?.posts
},
}
}
... and passing them to useState:
const [filteredArticles, setFilteredArticles] = useState(posts?.edges)
Then, I pass the state to a component:
router.isFallback ? (
// If we're still fetching data...
<div>Loading…</div>
) : (
<ArticleGrid myArticles={filteredArticles} />
This is necessary because another component will setFilteredArticles with a filter function.
But when we are passing the state to ArticlesGrid, the data is not ready when the component loads. This is confusing to me since we passing the state within a router.isFallback condition.
Even if we set state within useEffect...
const [filteredArticles, setFilteredArticles] = useState()
useEffect(() => {
setFilteredArticles(posts)
}, [posts?.edges])
... the data arrives too late for the component.
I'm new to Next.js. I can probably hack my way through this, but I assume there's an elegant solution.
Let's look at some useEffect examples:
useEffect(() => {
console.log("Hello there");
});
This useEffect is executed after the first render and on each subsequent rerender.
useEffect(() => {
console.log("Hello there once");
}, []);
This useEffect is executed only once, after the first render.
useEffect(() => {
console.log("Hello there when id changes");
}, [props.id]);
This useEffect is executed after the first render, every time props.id changes.
Some possible solutions to your problem:
No articles case
You probably want to treat this case in your ArticleGrid component anyway, in order to prevent any potential errors.
In ArticleGrid.js:
const {myArticles} = props;
if(!myArticles) {
return (<div>Your custom no data component... </div>);
}
// normal logic
return ...
Alternatively, you could also treat this case in the parent component:
{
router.isFallback ? (
// If we're still fetching data...
<div>Loading…</div>
) : (
<>
{
filteredArticles
? <ArticleGrid myArticles={filteredArticles} />
: <div>Your custom no data component... </div>
}
</>
)
}
Use initial props
Send the initial props in case the filteres haven't been set:
const myArticles = filteredArticles || posts?.edges;
and then:
<ArticleGrid myArticles={myArticles} />