如何不在Next.js动态路由之间保持状态?

时间:2020-07-28 21:52:34

标签: javascript reactjs react-hooks next.js next

我正在使用React / Next构建一个无头的电子商务站点,并且有一个[product].js动态路由,该路由用于生成所有产品页面,并使用getStaticPaths()getStaticProps()生成页面很好。

我正在useState中使用[product].js钩子来管理数字输入(用于数量)和其他一些事情。

加载的第一个产品页面工作正常,但是当我转到其他产品页面时,它们使用第一个产品的相同状态。

有没有办法使状态在两次路由更改之间不持久?

通过一些挖掘,我发现这是next的问题,并且在他们的积压中。它实质上是由于该组件没有密钥这一事实而产生的。这意味着在同一动态路由上的路由之间切换不能正确注册,并导致组件使用陈旧状态。

我发现的可能解决方案是:

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

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

    return {
        props: props
    }
}

这是我的实现方式,不适用于我:

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

我尝试将内容包装在另一个组件中,并为其添加一个键,就像这样,但是它仅适用于被包装的组件中包含的状态。

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

3 个答案:

答案 0 :(得分:1)

您可以在动态路由器上使用 useEffect hook 和 useRouter hook 来重置状态。

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 (
......
)
}

答案 1 :(得分:0)

您似乎遇到了与我发现的问题相同的问题: https://github.com/vercel/next.js/issues/9992

从我阅读的内容来看,要解决此问题,您需要做的就是更改getStaticProps以返回具有唯一键的对象:


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

  return {
    props: props,
    key: slug
  }
}

您之前所做的是将密钥传递给props对象而不是getStaticProps的root返回对象

答案 2 :(得分:0)

您可以使用useEffect挂钩重置状态

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(
    ...
  )
}

因此,当您的道具发生变化时-您的状态就会更新。