简体   繁体   中英

Passing Async State to Next.js Component via Prop

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 .

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} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM