【问题标题】:Retrieve Route Parameters in any Component在任何组件中检索路由参数
【发布时间】:2023-01-31 03:18:59
【问题描述】:

假设我的 URL 看起来像这样:

/blog/[post_id]/something

$post_id 向下传递到树中任何位置的任何组件的推荐方法是什么?

我知道如何使用getInitialProps 检索路由参数,但向下传递值总是让我很为难。

对于 pages,我可以在技术上使用 React 上下文,尽管对于这样一个微不足道的用例来说这似乎有点过大。

对于layouts,老实说,我完全迷路了,因为页面是布局的子项,getInitialProps 的返回值传递给页面而不是布局。

我的组件可以使用 useRouter 但这需要 useEffect 并且还会使我的组件依赖于路由本身......

任何的建议都受欢迎 (:

【问题讨论】:

    标签: next.js


    【解决方案1】:

    我的组件可以使用 useRouter 但这需要 useEffect 并且还会使我的组件依赖于路由本身......

    useRouter 似乎是这里显而易见的解决方案。根据路线,我不完全理解您对组件的担忧。我猜它确实使 Layout 不太灵活,因为它需要知道帖子 ID 存储在 post_id 查询变量中。但无论如何我都会这样做 :) 它为您提供了一种访问查询变量的好方法,这些查询变量可以在 BlogPost 之外的 Layout 中使用,或者在 @ 内部使用的深层嵌套组件中使用987654329@。

    使用 per-page layouts 方法:

    /components/Layout

    import { useRouter } from "next/router";
    import { ReactNode } from "react";
    
    export default function Layout({ children }: { children: ReactNode }) {
        const router = useRouter();
        return (
            <div>
                <h3>You are viewing post id #{router.query.post_id}</h3>
                {children}
            </div>
        );
    }
    

    /pages/blog/[post_id].jsx

    import Layout from '../../components/Layout';
    
    export default function BlogPost() {
        return <div>Hello World</div>
    }
    
    BlogPost.getLayout = function getLayout(page) {
        return (
            <Layout>
               {page}
            </Layout>
        )
    }
    

    /pages/_app.tsx(支持每页布局,从文档中复制)

    export default function MyApp({ Component, pageProps }) {
        // Use the layout defined at the page level, if available
        const getLayout = Component.getLayout || ((page) => page)
    
        return getLayout(<Component {...pageProps} />)
    }
    

    【讨论】:

      【解决方案2】:

      我认为最简单和最干净的方法是使用window.location.pathname。这将为您提供域名后的部分。例如对于

      http://localhost:3001/blog/[post_id]/something
      

      你会得到/blog/[post_id]/something

      const pathname=window.location.pathname
      const splittedPathname=pathname.split("/") // ['', 'blog', '[post_id]', 'something']
      
      const dynamicId=splittedPathname[2]
      

      您可以在useEffect 中运行以上代码并设置状态。或者您可以编写一个挂钩并在 dynamicId 组件下的组件中使用它

      import React, { useState, useEffect } from "react";
      
      const usePathname = () => {
        const [postId, setPostId] = useState("");
      
        useEffect(() => {
          const pathname = window.location.pathname;
          const splittedPathname = pathname.split("/");
          const dynamicId = splittedPathname[2];
          setPostId(dynamicId);
        }, []);
      
        return { postId };
      };
      
      export default usePathname;
      

      【讨论】:

        【解决方案3】:

        如果您正在寻找客户端渲染,useRouter 是最好的选择。如果您正在寻找 SSR 或 SSG,您应该使用 getStaticPropsgetServerSideProps

        【讨论】:

          【解决方案4】:

          一种选择是将 post_id 作为道具从页面组件传递到布局组件,然后向下传递到需要它的其他组件。另一种选择是使用像 Redux 或 MobX 这样的 React 状态管理库将 post_id 存储在商店中,并从树中的任何地方访问它。

          如果您想避免添加状态管理库,您可以创建一个自定义挂钩,从 URL 中检索 post_id 并将其作为状态返回。这个钩子可以用在任何需要 post_id 的组件中,并且可以避免将它作为 prop 传递到树中。

          自定义挂钩示例:

          import { useState, useEffect } from 'react';
          import { useRouter } from 'next/router';
          
          export default function usePostId() {
            const [postId, setPostId] = useState(null);
            const router = useRouter();
          
            useEffect(() => {
              setPostId(router.query.post_id);
            }, [router.query.post_id]);
          
            return postId;
          }
          

          然后可以在任何需要 post_id 的组件中使用这个钩子:

          import usePostId from './usePostId';
          
          function Component() {
            const postId = usePostId();
          
            // use postId in the component
          }
          

          【讨论】:

            猜你喜欢
            • 2022-01-24
            • 2021-02-13
            • 2017-07-14
            • 1970-01-01
            • 2018-01-11
            • 2018-08-01
            • 2021-07-14
            • 2016-04-14
            • 1970-01-01
            相关资源
            最近更新 更多