Search code examples
reactjsgatsby

Preserving prior form data when navigating back in Gatsbyjs


I have search page in Gatsbyjs where a filter form resides in the sidebar with multiple options. The page is generated from node.js using a template, where the product list and initial filter state is passed from page context.

When the user clicks a filtered product and navigates to the product page and then pushes the back button, the form is reset and the user has to make all the selections again. I tried to elevate the filter selections to local storage but how can I distinguish whether the user navigates to the search page using back button or via other link from menu selection for e.g? Here the code:

import * as React from 'react'
import { useState } from 'react'
import Layout from '../../components/layout'
import ProductList from '../../components/product-list'


const ProductPage = (props) => {
    const { products, filter, breadcrumb } = props.pageContext
    const {location} = props
    const initialFilter = {
      brands: [],
      types: [],
      ages: [],
      breeds: [],
      features: [],
      petTypes: [],
    
  }
  console.log(props)
  const filtered = Object.assign({},initialFilter,filter)
  const [checked, setChecked] = useState(filtered)
    

  const handleChange = (event, group) => {
      let checkedOptn = [...checked[group]]
      setChecked({
          ...checked,
          [group]: checkedOptn.indexOf(event.target.name) > -1 ? checkedOptn.filter(item => item !== event.target.name) :
              [...checkedOptn, event.target.name]

      })
  }
    
    const pageTitle = () => {
      if (location.pathname==='/urunler/kedi') {return 'Kedi Ürünlerimiz'}
      if (location.pathname==='/urunler/kopek') {return 'Köpek Ürünlerimiz'}
      return 'Ürünlerimiz'
    }
    
    return (
    <Layout location={location} pageTitle = {pageTitle()} crumbs={breadcrumb.crumbs}>
       <ProductList products = {products} checked={checked} handleChange={handleChange}/>
    </Layout>
    )
}

export default ProductPage

Is there a better approach for this problem? Thanks,


Solution

  • I ended up setting up an onClick listener on the filter where if a user clicks it will create a query string and navigate to the same page but with query parameters.

    Then on page load I read the location.search with contains the query, then parse the query and set the page state from the query. This way when the user refreshes the page or navigates to another page and comes with the back button to the original page, the selected filters are preserved.

    Here the code:

    const ProductPage = (props) => {
        const { products, breadcrumb } = props.pageContext
        const {location} = props
        const filter = qs.parse((location.search).substring(1))
        
        const initialFilter = {
          brands: [],
          types: [],
          ages: [],
          breeds: [],
          features: [],
          petTypes: [],
      }
      const filtered = Object.assign({},initialFilter,filter)
      const handleChange = (event, group) => {
          let checkedOptn = [...filtered[group]]
          let optionsSelected = {
            ...filtered,
            [group]: checkedOptn.indexOf(event.target.name) > -1 ? checkedOptn.filter(item => item !== event.target.name) :
                [...checkedOptn, event.target.name]
    
        }
        let queryString = qs.stringify(optionsSelected)
        console.log(queryString)
        const path = queryString.length > 0 ? `/urunler?${queryString}` :'/urunler'
          navigate(path)
      }
        
        const pageTitle = () => {
          if (location.pathname==='/urunler/kedi') {return 'Kedi Ürünlerimiz'}
          if (location.pathname==='/urunler/kopek') {return 'Köpek Ürünlerimiz'}
          return 'Ürünlerimiz'
        }
        
        return (
        <Layout location={location} pageTitle = {pageTitle()} crumbs={breadcrumb.crumbs}>
           <ProductList products = {products} checked={filtered} handleChange={handleChange}/>
        </Layout>
        )
    }
    
    export default ProductPage