Nathanael
Nathanael

Reputation: 1002

Premature list sorting in React Native

I'm somewhat confused by the way a certain array is being sorted by a redux function. I have a list of employees which I need to sort by name.

For example I have in my default reducer state:

employees = [Nate, John, Michael]

In the screen where this prop is rendered, I do a console.log when the component is mounted and I get:

[Nate, John, Michael]

Now, this is where it gets strange. I have an onPress function that reorders the list alphabetically. I'm also console logging the list's value in the screen (before the action is fired), in the action (where the sorting is taking place), and in the reducer. The console.log BEFORE the action fires returns a sorted list.

reorderList() {
  if(this.props.employees){
      console.log("SCREEN", this.props.employees);
      this.props.reorderList(this.props.employees);
  }
}

Returns:

SCREEN: [John, Michael, Nate]

It's as if the action is happening before the console.log, but I don't see how that would be possible unless I'm misunderstanding the synchronicity of RN functions.

Here's the function inside of the action which is sorting the list. I've put the same function inside of the reducer, and the action/screen logs are still returning the prematurely sorted array.

export const reorderList = (employees) => {
    console.log("ACTION", employees); // returns "ACTION: [John, Michael, Nate]"
    var items = employees;
    employees.sort(function(a, b){
        var nameA = a.name.toUpperCase();
        var nameB = b.name.toUpperCase();
        if (nameA < nameB) {
            return -1;
        }
        if (nameA > nameB) {
            return 1;
        }
        return 0;
    });
    return {
        type: "reorder_list",
        payload: items
    }
}

It seems as if I'm misunderstanding something within Redux?

Upvotes: 1

Views: 354

Answers (1)

Elias Toivanen
Elias Toivanen

Reputation: 848

You are most likely witnessing a well-known flaw in JS (and other programming languages). Namely, the sort method both mutates the array behind this in-place and returns this.

The fix is to copy the array into items and sort it, leaving employees untouched:

const items = [...employees]
items.sort((a,b) => a.localeCompare(b) )

PS. I recommend to put the sorting code in the reducer.

Upvotes: 1

Related Questions