Christian Matthew Christian Matthew - 3 months ago 30
React JSX Question

React: array order is completely random - what determines the array order per the syntax

I have done tutorials and have seen examples where the array list item that is dynamically generated works exactly as intended. For some reason, in the code I am having to map in this particular array list is not generating the array list in any discernible order.

Reason being... From what I seen every time an action is added the key and index and other parameter is "adjusted" on the fly... leading to something completely random.

***Updated the description to be much more accurate to what is occuring based on my code base. I have learned we are using imuttable.js
More info here https://facebook.github.io/immutable-js/ and because of this there are certain things happening prior to the object being mapped...

For example we are using filter for a json object in our this.props

it is written as follows:

const filteredConstant = jsonObjects.filter((jsonObject) => {
return (jsonObject.status === status.APPROVED)
}


From the documentation in immutable it says filter will do the following

Seq({a:1,b:2,c:3,d:4}).filter(x => x % 2 === 0)
// Seq { b: 2, d: 4 }


From here we can rework the const / variable and now use map() to map the object. The below code did not work in the sense that open adding items to the object of jsonObject2 would produce random results. The key and even if I added an index there would be no rhyme or reason as to what the order would be... intended result would be oldest - newest data entry or ascending.

filteredConstant.valueSeq().map((jsonObjectNew, //index) => {
// code here
key={jsonObjectNew.id} //index={index} (//doesn't work either way)
}


apparently valueSeq() doesn't have an affect. Introducing a timestamp appended to a unique id doesn't work either.

Like I said previously it seems as if every-time there is a new entry it "remaps" and thus reorders randomly what is going on. I could be interpreting what the key actually is... I still haven't figured out how and where the key is being generated ideally from the server side. But even in terms of a key that is base64 for example would still have to go in some type of order based on letters and numerics? Am I wrong to think this?

Alas, I was able to create a fix and I will share that below. But more insight into this would be appreciated.

In jsfiddle I cannot replicate the issue but if any help can be offered on what exactly controls the array order and or new data entering into the object would said action have on the effect of the overall order?

Answer

So I was able to do a fix and there is something that I had to grasp in order to understand what the map'ed list was not in any type of order.

The answer lies in the fact that I was mapping an object... It wasn't an array or map object that was being inserted to dynamically... It was simply an object that for all intents and purposes is a dictionary of dictionaries.

Per the example react gives they dynamically build and array that is of an order per insertion... new item at the bottom. here is what that array looks like.

[
    {
        "id": 1388534400000,
        "author": "Pete O'malley",
        "text": "Hey there!"
    },
    {
        "id": 1420070400000,
        "author": "Paul O’Shannessy",
        "text": "React is *great*!"
    },
    {
        "id": 1470769287060,
        "author": "Christian",
        "text": "how are you"
    }
] = JSON.stringify(this.props.data, null, 4)

and so on...

My object that was being used was not like this at all... It is just an object of objects.

Here is an example with 2 entries.

{
  "93b1keyId": {
    "xxxxx": "",
    "xxxxx": {
        "xxxx": "xxxx",
        "xxxxx": [
            {
                "xxx": "xxxx",
                "xxxxx": "xxxxx "
            }
        ],
        "xxxxx": "",
        "xxxxx": "",
        //code here
    },
    "Date": "2016-08-16",
    "xxxxxx": "xxxxxxxx",
    "timeCreated": "2016-08-16 17:49:39 pm -0400",
    "xxxxx": {
        "xxxxxx": "xxxxxx",
        "xxxxxxx": "xxxx"
    },
    "xxxxxx": xxxxxx,
    "id": "93b1KeyId",
    "xxxxxx": "xxxxx"
},
"ed79KeyId": {
    "xxxxx": "",
    "xxxxx": {
        "xxxx": "xxxx",
        "xxxxx": [
            {
                "xxx": "xxxx",
                "xxxxx": "xxxxx "
            }
        ],
        "xxxxx": "",
        "xxxxx": "",
        //code here
    },
    "Date": "2016-08-16",
    "xxxxxx": "xxxxxxxx",
    "xxxxx": {
        "xxxxxx": "xxxxxx",
        "xxxxxxx": "xxxx"
    },
    "xxxxxx": xxxxxx,
    "id": "ed79613e-d4bf-4fb4-993f-c212993d5d3b",
    "xxxxxx": "xxxxx"
  }
} = JSON.stringify(jsonObjectOriginal, null, 4)

So as you see this is not an array... it is just a dictionary of dictionaries. objects in objects.

Per this entry I am able to confirm with reasonable assurance that order of dictionary objects are not ordered.

Stack question regarding property order

In particular see section 12.6.4 of the ECMAScript specification:

The mechanics and order of enumerating the properties ... is not specified.

&

4.3.3 Object

An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.

What was confusing about the situation is that it is a little misleading to consider "mapping" to be iterative of insertion order if what it is mapping is an unordered object.

Per the mozilla their documentation states the following.

A Map object iterates its elements in insertion order — a for...of loop returns an array of [key, value] for each iteration.

Again, that is only if you are inserting to the actuall map object itself... which for me was not the case.

So, the answer...

I had to re-sort the object upon mapping the React function which displays to the UI... I used sortBy which is an immutable sub method of the map() method. Doc information can be found here: immutable sortBy method

{filteredConstant.sortBy(sortBy => sortBy.timeCreated).map((jsonObject2) => {  
    //code here

So now, the new mapped object is reordered correctly based on insertion time and displayed to the UI correctly. I enjoyed learning / working through this one!!! but I feel mozilla should perhaps update that page.

I verified my "theory" by studying the jsonObjectOriginal and jsonObjectNew... The original was the one taking in random order.

Comments