最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to NOT persist state between Next.js dynamic routes? - Stack Overflow

programmeradmin2浏览0评论

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.

I'm using useState hook within [product].js to manage a number input (for quantity) and a couple of other things.

The first product page loaded works fine, but when I go to other product pages, they use the same state from the first product.

Is there a way to have the state NOT persist between route changes?

Through some digging, I found that this is an issue with next and is in their backlog. 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.

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:

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

Since this new keyed component is only in the return statement and does not encapsulate the state hook, it does not work. This does reset the state however, for any components found within wrapped component.

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.

I'm using useState hook within [product].js to manage a number input (for quantity) and a couple of other things.

The first product page loaded works fine, but when I go to other product pages, they use the same state from the first product.

Is there a way to have the state NOT persist between route changes?

Through some digging, I found that this is an issue with next and is in their backlog. 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.

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:

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

Since this new keyed component is only in the return statement and does not encapsulate the state hook, it does not work. This does reset the state however, for any components found within wrapped component.

Share Improve this question edited Dec 21, 2021 at 2:06 Lee Buckle asked Jul 28, 2020 at 21:52 Lee BuckleLee Buckle 7492 gold badges9 silver badges17 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 11

You can use useEffect hook and useRouter hook at dynamic router to reset the 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 (
......
)
}

It seems that you've encountered the same issue thread that I've found: 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:


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

You can use useEffect hook to reset 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.

发布评论

评论列表(0)

  1. 暂无评论