使用动态路由、下一个 JS 和 useEffect 在 React 中获取数据

Posted

技术标签:

【中文标题】使用动态路由、下一个 JS 和 useEffect 在 React 中获取数据【英文标题】:fetching data in React with DynamicRoutes, nextJS and useEffect 【发布时间】:2021-02-26 15:26:16 【问题描述】:

我有一个博客链接。链接是带有博客 ID 的动态路由。它是来自 Next 的 Link 包装器。

//link
<h3 className="blogTitle">
    <Link href="[blog]" as=props.item.postingId>props.item.title</Link>
</h3>

现在我想将“博客 ID”传递给组件并在新页面中显示数据。

//page where link leads to
const ad = () => 
    const router = useRouter()
    const 
        query: blog,
     = router
    
    const [data, setData] = useState(false);
    const [loading, setLoading] = useState(false);   
                   
    console.log('....outside useEffect log', blog)
    useEffect(() => 
        console.log('useEffect consolelog', blog); 
        axios.get('httpwww.blogapiadress.com/'+ ad)
            .then(response => setData(response.data))
            .then(setLoading(false))
    , [])
  
    return( 
        <Container fluid className="padding0">
            /// data should be here.
        </Container>
    );

    
export default ad;

问题:useEffect console.log('blog', blog) 返回未定义,因此路由器不会从查询中返回值。但是,在useEffect 之外它确实如此。如何解决这个问题,我想获取与路由器查询相关的数据?

因为 axios 得到的是 undefined 而不是博客 ID,所以我得到的是 404。

【问题讨论】:

【参考方案1】:

您可以使用getStaticProps() 在构建时获取博客数据。

例子:

// posts will be populated at build time by getStaticProps()
function Blog( posts ) 
  return (
    <ul>
      posts.map((post) => (
        <li>post.title</li>
      ))
    </ul>
  )


// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries. See the "Technical details" section.
export async function getStaticProps() 
  // Call an external API endpoint to get posts.
  
  // Access route params:
  const blog = context.query.blog // or context.params.blog for parametrized routes
  return 

  const res = await fetch('https://...')
  const posts = await res.json()

  // By returning  props:  posts  , the Blog component
  // will receive `posts` as a prop at build time
  return 
    props: 
      posts,
    ,
  


export default Blog

更多关于NextJS docs的信息。

【讨论】:

【参考方案2】:

寻找答案几个小时,当我在堆栈上发布问题时......我想出了答案。

所以问题是在构建时查询为空,下一代静态生成 https://nextjs.org/docs/api-reference/next/router#router-object

我还没有找到最佳解决方案,但我找到了可行的解决方案。 我从windows.location href获得了博客ID

  useEffect(()=>
    const last = window.location.href.split('/').pop();
    console.log('last', last)
    axios.get('https://blogpostings.com/'+last)
        .then(response => setData(response.data))
      , [])

我不确定它是否正确或好方法,但它有效。 我希望有人会觉得这很有帮助。

【讨论】:

【参考方案3】:

如果要从链接中获取查询参数,需要在url末尾插入:https://sample-link.com?blog=123

然后和你上面的代码一样:

import  useRouter  from 'next/router'

const router = useRouter()

const 
   query: blog
 = router;

console.log("blog: ", blog)

结果:

blog: 123

【讨论】:

【参考方案4】:

我认为您不需要使用全局窗口对象来访问与您的路由相关的动态数据——您应该能够使用 Next 路由器。我认为您定义href 的方式- Link 唯一需要的道具会导致问题。查看文档和您当前的示例,您可能想要使用以下内容:

        <Link
          href=
            pathname: '/[blog]',
            query:  blog: props.item.postingId ,
          
        >
           <a>props.item.title</a>
        </Link>

     // or

     <Link href=`/$encodeURIComponent(props.item.postingId)`>
        <a>props.item.title</a>
    </Link>

那么您应该能够使用路由器正确访问 [博客](即您的发布 ID)。例如,如果您的路由是由/[blog].js 动态定义的,您可以使用以下内容:

     import  useRouter  from 'next/router'

     const ad = () => 
        const router = useRouter()
        const  blog  = router.query

        const [data, setData] = useState(false);
        const [loading, setLoading] = useState(false);
               
        useEffect(()=>
             axios.get('httpwww.blogapiadress.com/'+ blog)
                 .then(response =>  
                    setData(response.data)
                    setLoading(false)
              )
         , [])


    if (loading || !data) return <div> Loading... </div>

    return( 
       <Container fluid className="padding0">
         /// Render data
      </Container>
    );


export default ad;

【讨论】:

以上是关于使用动态路由、下一个 JS 和 useEffect 在 React 中获取数据的主要内容,如果未能解决你的问题,请参考以下文章

React useEffect useContext - 上下文适用于某些组件,但不适用于动态路由

如何使用/不使用 useEffect 钩子在 React JS 函数中获取更改的(新)状态值?

React useEffect 不会在路由更改时触发

AngularJS - 基于路由动态加载外部 JS

如何使用 useEffect 和 Context API 来检查用户是不是登录并保护路由?

如何在 react 中的新路由更改上使用 useEffect 重新渲染变量