0

I have an array that consists of some geoJSON data. I want to create a new array consisting of the data with one more key in the properties section. But it keep changing the original array. How can I prevent it from changing the orignial array?

const [citys, setCitys] = useState(someGeoJson)
const [manipulatedArray, setManipulatedArray] = useState([])

function createManiArray() {
  let currentManipulatedArray = []
  citys.features.forEach((city) => {
    let currentCity = city
    currentCity.properties = { ...city.properties,
      value: Math.random()
    }
    currentManipulatedArray .push(currentCity)
    //My problem now is that this changes the orginal city array, how can i prevent that from happening?

  })
  setManipulatedArray(currentManipulatedArray)
}
  • 1
    @lejlun I edited the quetion now, thanks for pointing it out. – Surface Nowy Apr 12 '22 at 12:00
  • 1
    Does this answer your question? [How do you clone an array of objects in JavaScript?](https://stackoverflow.com/questions/597588/how-do-you-clone-an-array-of-objects-in-javascript) – jeremy-denis Apr 12 '22 at 12:01

2 Answers2

1

I think many of this kind of problems arise in the moment you use a forEach to essentially map values to another list. The "map" method on an array does exactly that

const manipulated = citys.map(city => ({
    ...city.properties,
    value: Math.random
}));

This way you don't have to worry about references / modifying your original array.

P.S. it is also worth noting that storing a variable with useState that's essentially derived from another state variable is not an ideal thing to do. You might want to reconsider how your state is managed to essentially have a single source of truth (being your "citys") variable :)

Jaco
  • 21
  • 4
0
  1. You're not using setManipulatedArray to set the state.

  2. You should be using map to create a new array of objects instead of mutating the original array.

const [cities, setCities] = useState(someGeoJson);

const [manipulatedArray, setManipulatedArray] = useState([]);

function createManiArray() {

  // Create a new array of objects with an updated
  // properties object
  const updated = cities.features.map(city => {
    return {
      ...city,
      properties: {
        ...city.properties,
        value: Math.random()
      }
    };
  });
  
  // Set the new state with that array
  setManipulatedArray(updated);

}
Andy
  • 61,948
  • 13
  • 68
  • 95
  • This will only return the properties if I am not wrong, but what if I want the whole Object + the value inside the properties? Original:{geometry:{...},properties:{name:Oslo,country:Norway}} Manipulated:{geometry:{...},properties:{name:Oslo,country:Norway,value:15}} – Surface Nowy Apr 12 '22 at 12:13
  • Ah, yes. Updated the answer. – Andy Apr 12 '22 at 12:18
  • This tells me ',' expected on the city.properties: line? I tried ...city, but didnt help – Surface Nowy Apr 12 '22 at 12:27
  • I forgot a comma, and realised it should have been `properties` not `city.properties`. See updated. @SurfaceNowy. – Andy Apr 12 '22 at 12:28
  • @SurfaceNowy, as Jaco mentioned, you should probably remove the `manipulatedArray` state altogether and just use `setCities(updated)` but ultimately it depends on your use-case. – Andy Apr 12 '22 at 12:37
  • 1
    This was more of an example in a attempt to see what caused the issue I had longer down in the function. I will use this function to filter a bigger array and combine that with another but I had some issues with the other getting changed but now it is all solved thanks to your answer. – Surface Nowy Apr 12 '22 at 21:42