[SOLVED] how can i reverse the order of an array with usestate

Issue

I have connected to an api and have pulled some data into my project with the name of ‘data’. This data is being rendered dynamically into a card component. I am now trying to reverse the order of these cards on the click of a button with useState but cannot figure it out. Below is what i have so far:

import React, { useState } from 'react'
import './App.scss'
import { useQuery } from '@apollo/react-hooks'
import GET_PRODUCTS_IN_COLLECTION from './gql/getCollection'
import ProductCard from './components/ProductCard/ProductCard'

const App = (props) =>  {

  const {data, loading, error} = useQuery(GET_PRODUCTS_IN_COLLECTION, {
    variables: {
      count: 10,
      handle: 'skateboard'
    }
  })

  const [reverseData, setReverseData] = useState(data)

  const reverseOrder = () => {
    let newArray = reverseData.slice().reverse()
    setReverseData(newArray)
  }
  

  if(loading) {
    // Data is still loading....
    return (<div className="App">Loading....</div>)
  }

  return (
    <div className="App">
      <header className="App-header">
      </header>
      <main>
        
        <div className="buttonGroup">{reverseData.join(", ")}
          <button onClick={reverseOrder}>Reverse Product Order</button>
          <button>Price High to Low</button>
          <button>Price Low to High</button>
          <button>Display 9 products</button>
          <p>{reverseData}</p>
        </div>

        {/* 
          Your render components go here
        */} 

        <div className="ProductList">
           {data.collectionByHandle.products.edges.map(product => {
             return (<ProductCard productData={product} />)
           })}
        </div>
      </main>
    </div>
  )
}

export default App


can someone tell me where I am going wrong.

Solution

You need not store the data fetched via useQuery in the state. Simply store the reversal state, and use that to manipulate the render. If the reversed state is true, use .slice().reverse() to reverse you array before render.

const [reversed, setReversed] = useState(false)

const reverseOrder = () => {
  setReversed(!reversed)
}

return (
// ...
    <div className="ProductList">
      {reversed
        ? data.collectionByHandle.products.edges
            .slice()
            .reverse()
            .map((product) => {
              return <ProductCard productData={product} />;
            })
        : data.collectionByHandle.products.edges.map((product) => {
            return <ProductCard productData={product} />;
          })}
    </div>
// ...
)

The key here is to reverse the array. In your case the "edges" property seems to be the array. Since reverse changes the array in place, we use slice to create a copy and then reverse, to prevent the original array from being mutated.

Answered By – Shreshth

Answer Checked By – Timothy Miller (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *