简体   繁体   English

如何不在 Next.js 动态路由之间保留 state?

[英]How to NOT persist state between Next.js dynamic routes?

I'm building a headless eCommerce site using React/Next and have a [product].js dynamic route which is used to generate all product pages, using getStaticPaths() and getStaticProps() which generates the pages fine.我正在使用 React/Next 构建一个无头电子商务网站,并有一个[product].js动态路由,用于生成所有产品页面,使用getStaticPaths()getStaticProps()可以很好地生成页面。

I'm using useState hook within [product].js to manage a number input (for quantity) and a couple of other things.我在[product].js中使用useState挂钩来管理数字输入(用于数量)和其他一些事情。

The first product page loaded works fine, but when I go to other product pages, they use the same state from the first product.加载的第一个产品页面工作正常,但是当我 go 到其他产品页面时,他们使用与第一个产品相同的 state。

Is there a way to have the state NOT persist between route changes?有没有办法让 state 在路线更改之间不存在?

Through some digging, I found that this is an issue with next and is in their backlog.通过一些挖掘,我发现这是 next 的问题,并且在他们的积压中。 It essentially stems from the fact that the component doesn't have a key.它本质上源于组件没有密钥的事实。 This means switching between routes on the same dynamic route doesn't register correctly and causes the component to use stale state.这意味着在同一动态路由上的路由之间切换不会正确注册并导致组件使用陈旧的 state。

A possible solution I found was this:我发现的一个可能的解决方案是:

export async function getStaticProps({params}) {
    const props = await getData(params);

    // key is needed here
    props.key = data.id; 

    return {
        props: props
    }
}

This is my implementation which doesn't work for me:这是我的实现,对我不起作用:

export default function ProductPage(props) {

  // this state doesn't reset between dynaic route changes
  const [quantity, setQuantity] = useState(1)

  return(
    ...
  )
}

export async function getStaticProps({ params }) {
  const slug = params.product
  const props = await client.query({
    query: singleProductQuery,
    variables: { id: slug }
  })

  props.key = props.data.product.slug

  return {
    props: props
  }
}

I tried wrapping the contents within another component and adding a key to that, like so, but it only works for the state contained within components that are wrapped.我尝试将内容包装在另一个组件中并为其添加一个密钥,就像这样,但它仅适用于包含在包装的组件中的 state。

return(
  <OuterComponent key={props.id}>
    // components within here, that have their own state, now work
  </OuterComponent>
)

It seems that you've encountered the same issue thread that I've found: https://github.com/vercel/next.js/issues/9992您似乎遇到了与我发现的相同的问题线程: https://github.com/vercel/next.js/issues/9992

It seems from what I've read that to fix your case, all you need to do is change your getStaticProps to return an object with a unique key:从我读到的内容看来,要解决您的问题,您需要做的就是更改您的getStaticProps以返回具有唯一键的 object :


export async function getStaticProps({ params }) {
  const slug = params.product
  const props = await client.query({
    query: singleProductQuery,
    variables: { id: slug }
  });

  return {
    props: props,
    key: slug
  }
}

What you've been doing previously is passing a key to the props object instead of root return object for getStaticProps您之前所做的是将密钥传递给道具 object 而不是 root 返回 object 以获得getStaticProps

You can use useEffect hook to reset state您可以使用 useEffect 挂钩重置 state

export default function ProductPage(props) {



// this state doesn't reset between dynaic route changes
  const [quantity, setQuantity] = useState(1)

  useEffect(() => {
    setQuantity(props.quantity) // <-- this props comes from getStaticProps
}, [props]) // <--- useEffect will keep tracking changing props



  return(
    ...
  )
}

So when your props changes - your state updates.因此,当您的道具发生变化时 - 您的 state 会更新。

You can use useEffect hook and useRoute r hook at dynamic router to reset the state.您可以在动态路由器上使用useEffect hook 和useRoute r hook 来重置 state。

import {useState, useEffect} from 'react'
import {useRouter} from 'next/router'

const ProductPage = (props) => {
const [state, setState] = useState(someState)
const dynamicRoute = useRouter().asPath
useEffect(() => {
  setState(resetState) // When the dynamic route change reset the state
}, [dynamicRoute])
//Some other logic
return (
......
)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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