Home > OS >  how can i reverse the order of an array with usestate
how can i reverse the order of an array with usestate

Time:02-19

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.

CodePudding user response:

.reverse() mutates the array, and you shouldn't mutate useState values directly. Instead of this you need to create the new value:

  const reverseOrder = () => {
    let newArray = [...reverseData]
    newArrray.reverse()
    setReverseData(newArray)
  }

So, you create a new array from your state, mutate it and assign to the state

CodePudding user response:

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.

  • Related