【问题标题】:Query values lost on page refresh in Next js? [Example given]Next js中页面刷新时查询值丢失? [给出的例子]
【发布时间】:2021-02-23 02:51:41
【问题描述】:

我正在制作一个只有两页的简单 Next Js 应用程序..

index.tsx:

import React from "react";
import Link from "next/link";

export default function Index() {
  return (
    <div>
      <Link
        href={{
          pathname: "/about",
          query: { candidateId: 8432 }
        }}
        as="about"
      >
        Go to the about page
      </Link>
    </div>
  );
}

根据上面的代码,点击Go to the about page会转到关于页面,使用query我也会在关于页面中收到传递的查询值。

about.tsx

import React from "react";
import Router, { withRouter } from "next/router";

function About({ router: { query } }: any) {
  return (
    <div>
      Candidate Id: <b> {query.candidateId} </b>
    </div>
  );
}

export default withRouter(About);

这会显示值,但是当我们在 /about 页面时刷新页面时,收到的 candidateId 会消失。

要求:请帮助我保留从一个页面传递到另一个页面的查询值,即使在页面刷新时也是如此。

注意:根据我的要求,我不应该在导航时在 url 上显示canidateId,因此我使用as 方法。我知道如果我删除@987654334,我可以实现它@ 但我无法在导航时在索引页面中删除它。原因是这将导致在 url 中显示不想要的候选 ID ..

尝试了这个解决方案:https://stackoverflow.com/a/62974489/7785337 但这会在页面刷新时提供 empty query 对象。

困扰了很长时间,请帮助我。

【问题讨论】:

  • AFAIK,“路由状态”是相当短暂的,它真的只存在于路由转换期间。重新加载页面不会重新加载过渡。我认为您需要将传递的数据保存到 localStorage 或任何可用的数据,在页面加载/重新加载后可以访问。
  • @DrewReese,感谢您的评论,我认为其他一些人也面临同样的问题,例如stackoverflow.com/questions/61891845/…,并且建议的解决方案对我不起作用.. 如果您能帮助我,请用您的解决方案分叉我的代码框并将其发布为答案.. 我只是请求您是否可以这样做.. 因为我以与您不同的方式看待事物,并且我从您那里学到了很多东西.. 如果您愿意,请帮助我可以..谢谢..
  • @DrewReese,兄弟你能帮我吗stackoverflow.com/questions/65504354/…
  • @DrewReese,在这种情况下我们可以使用 React 上下文 API 吗?
  • 看起来 TJ 在这方面做得很好。我不反对他在那里说的任何话。在没有看到你的实际代码的情况下,完全基于他的话和我对 react-metrics 文档的检查,我会说,是的,React Context API 可能会在这里提供帮助,尽管看起来 react-metrics 可能已经有自己的上下文和提供者.

标签: javascript reactjs next.js server-side-rendering


【解决方案1】:

index.tsx 文件

保持代码不变。

   import React from "react";
   import Link from "next/link";
   
   export default function Index() {
     return (
       <div>
         <Link
           href={{
             pathname: "/about",
             query: { candidateId: 8432 }
           }}
           as="about"
         >
           Go to the about page
         </Link>
       </div>
     );
}

AboutUs.tsx

代码从这里开始

在 useEffect 中添加路由器作为依赖项应该可以解决问题。

  import Router, { useRouter } from "next/router";
  import React, { useState, useEffect } from 'react';

  function About({ router: { query } }: any) {
    const route = userRouter();
    const [candidateId, setCandidateid] = useState();

    useEffect(() => {
    const {candidateId} = router.query  
    if(candidateId) {
     setCandidateid(candidateid)
   }},[router])  //Here goes the dependency

    return (
      <div>
        Candidate Id: <b> {candidateId} </b>
      </div>
    );
  }
  
  export default (About);

【讨论】:

    【解决方案2】:

    更新到 Next.JS 10。它带有 Automatic Resolving of href 可以解决您的问题。

    【讨论】:

      【解决方案3】:

      我最好的选择是将candidateId 存储在客户端的加密会话中。您可以读取/验证 getServerSideProps() 中的 cookie 并将其内容传递给页面组件。如果这听起来可行,我建议您查看next-iron-session

      另一种方法是检查candidateId 是否存在于getServerSideProps() 的查询对象中。如果确实如此,则将其直接传递给页面组件。如果没有,要么在别处获取它,重定向,要么传递一些默认值。将以下起始代码附加到您的 about.tsx

      /* ... */
      
      export function getServerSideProps({ query }: any) {
        // if query object was received, return it as a router prop:
        if (query.candidateId) {
          return { props: { router: { query } } };
        }
        // obtain candidateId elsewhere, redirect or fallback to some default value:
        /* ... */
        return { props: { router: { query: { candidateId: 8432 } } } };
      }
      

      【讨论】:

        【解决方案4】:

        如果您不想使用查询参数,您可能需要创建一个“存储”来保存在整个页面中持续存在的变量。

        示例代码如下。

        //candidatestore.js
        export const CandidateStoreContext = createContext()
        
        export const useCandidateStore = () => {
            const context = useContext(CandidateStoreContext)
            if (!context) {
                throw new Error(`useStore must be used within a CandidateStoreContext`)
            }
            return context
        }
        
        export const CandidateStoreProvider = ({ children }) => {
        
            const [candidateId, setCandidateId] = useState(null);
        
            return (
                <CandidateStoreContext.Provider value={{ candidateId, setCandidateId }}>        
                                {children}    
                </CandidateStoreContext.Provider >
        
            )
        }
        

        然后您需要将 Provider 包裹在您的应用周围,例如

        <CandidateStoreProvider><App /></CandidateStoreProvider>
        

        这样你就可以在你的索引页面和关于页面的任何地方使用如下。

        const { candidateId, setCandidateId } = useCandidateStore()
        

        UseContext

        在您的代码中,它可能看起来像这样。

        import React from "react";
        import Link from "next/link";
        import { useCandidateStore } from './candidatestore'
        
        export default function Index() {
          const { candidateId, setCandidateId } = useCandidateStore()
          useEffect(() => {
             setCandidateId(thecandidateId)
          })
          return (
            <div>
              <Link
                href={{
                  pathname: "/about",
                }}
                as="about"
              >
                Go to the about page
              </Link>
            </div>
          );
        }
        
        function About({ router: { query } }: any) {
        
          const { candidateId, setCandidateId } = useCandidateStore()
          return (
            <div>
              Candidate Id: <b> {candidateId} </b>
            </div>
          );
        }
        

        【讨论】:

          【解决方案5】:

          尝试删除as="about",然后再次导航到“关于”页面,问题应该消失了。 Codesandbox

          【讨论】:

          • 我已经提到过,如果我删除as,这将起作用,但我不应该这样做,因为这会导致在网址中显示candidateId..
          猜你喜欢
          • 2022-11-13
          • 1970-01-01
          • 2019-09-12
          • 1970-01-01
          • 1970-01-01
          • 2016-01-26
          • 1970-01-01
          • 2020-08-28
          • 2020-09-07
          相关资源
          最近更新 更多