ReactFix
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • React
  • React Native
  • Programming
  • Object Oriented Programming

Sunday, December 18, 2022

[FIXED] How can I sort an array of objects from an API before passing them into a react component?

 December 18, 2022     apollo, graphql, javascript, reactjs   

Issue

Hello I'm fairly new to react/js and I am trying to sort some data that I am fetching from the an api using Apollo then render the data into a grid. When I try to use the sort() function I get and error in the console "TypeError: Attempting to change configurable attribute of unconfigurable property.". Can anyone help explain what I'm doing wrong? Many thanks

This is the code I've tried. It works without the data.ammo.sort method.

I was expecting the data to be rendered in order sorted by damage

import { useQuery, gql } from '@apollo/client';
import AmmoBox from "./components/Ammo"
import {Grid} from "@chakra-ui/react"

export const GET_AMMO = gql
`{
    ammo{
        item {
            id
            name
            shortName
        }
        damage
        penetrationPower
        caliber
    }
}`

function App() {

  const { loading, error, data } = useQuery(GET_AMMO);

  if (loading) return 'Loading';
  if (error) return 'Error';

  console.log(data.ammo);

  //sort data here before mapping to AmmoBox component*
  data.ammo.sort((a, b) => a.damage - b.damage);

  return (
    <Grid templateColumns='repeat(5, 1fr)' gap={6}>
      {data.ammo
      .map((ammos) => (
        <AmmoBox name={ammos.item.name} caliber={ammos.caliber} penetration={ammos.penetrationPower} damage={ammos.damage}/>))}
    </Grid>
  );
}

export default App;

Solution

Since the error says you can't change data.ammo, spread the data to a new (shallow-copied) array sortedArray and apply .sort() method to this new array.

Check code below:

function App() {

  const { loading, error, data } = useQuery(GET_AMMO);

  if (loading) return 'Loading';
  if (error) return 'Error';

  console.log(data.ammo);

  // Spread ammo data to a new shallow-copied array and use sort() function on the new array
  const sortedArray = [...data.ammo].sort((a, b) => a.damage - b.damage);

  return (
    <Grid templateColumns='repeat(5, 1fr)' gap={6}>
      {sortedArray
      .map((ammos) => (
        <AmmoBox name={ammos.item.name} caliber={ammos.caliber} penetration={ammos.penetrationPower} damage={ammos.damage}/>))}
    </Grid>
  );
}

Mozilla Docs - Array.prototype.sort() :

The sort() method returns a reference to the original array, so mutating the returned array will mutate the original array as well.

In case you want sort() to not mutate the original array, but return a shallow-copied array like other array methods (e.g. map()) do, you can do a shallow copy before calling sort(), using the spread syntax or Array.from().



Answered By - watsum08
Answer Checked By - - Marie Seifert (ReactFix Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Newer Post Older Post Home

Featured Post

Is Learning React Difficult?

React is difficult to learn, no ifs and buts. React isn't inherently difficult to learn. It's a framework that's different from ...

Total Pageviews

Copyright © ReactFix