Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

React child not updating state of parent using handler prop and custom sort method

I have the following parent component. It makes use of dynamicSort, a custom sort function for an array of objects that returns a sorted array of objects by the specified key. I have confirmed that the sort function works:

import React, { useState, useEffect } from 'react';
import { dynamicSort } from '../helpers';
import Container, ChildHeader, Childbody, Spinner, etc...

const Parent = () => {
  const [listItems, setListItems] = useState([]);

  useEffect(() => {
    // fetch list items and set them here on component mount
    // this works currently
  }, [])

  const sortList = column => {
    setListItems(prev => dynamicSort(prev, column, 'asc'));
  };

  return (
    <Container>
        <ChildHeader
          sortList={sortList}
        />
        <ChildBody>
          {listItems !== [] ? (
            listItems.map(item => {
              return (
                <ChildRow
                  key={item.id}
                  rowItem={item}
                />)
            })
          ) : (
            <Spinner />
          )}
        </ChildBody>
    </Container>
  );
};

export default Parent;

Inside of childHeader, I call the prop sortList on a heading click like this:

const ChildHeader = ({ sortList }) => {
    return (
      <HeaderContainer>
        <Column1
          onClick={() => {
            sortList('Column1'); // This should sort and reset the state of the list in the parent
          }}
        >
          {'Column Label'}
        </Column1>
        // More columns...
      </HeaderContainer>
    );
};

export default ChildHeader;

I have confirmed that handler is called when the child component is clicked. But for some reason the state does not update on the parent list. The even weirder thing to me is that if I change the sortList method in the parent to the following code, the list updates on child click.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const sortList = column => {
    setListItems(prev => prev.slice(0, 3); // Using slice instead of my custom sort method
};

This makes me think that there is something wrong with my sort method. I have confirmed that the sort method does return an array of objects and that it is sorting correctly. Any have a clue what’s happening? I’ll include the sort method below just for kicks:

export const dynamicSort = (list, column, direction) => {
  const compare = (a, b) => {
    switch (column) {
      case 'Column1':
        if (direction === 'asc') {
          if (a.key1 > b.key1) {
            return 1;
          }
          if (a.key1 < b.key1) {
            return -1;
          }
          return 0;
        }
        if (direction === 'desc') {
          if (a.key1 < b.key1) {
            return 1;
          }
          if (a.key1 > b.key1) {
            return -1;
          }
          return 0;
        }
      // More cases following below

      default:
        return null;
    }
  };
  return list.sort(compare); // This does return an array of objects sorted correctly by key 
}

>Solution :

Because you’re not actually updating state. You’re mutating state. According to the documentation for sort:

The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted.

So you’re updating state to the same array reference, which means React has no way to know that state has been modified in any way.

Probably the simplest approach would be to modify your dynamicSort function to sort a new array reference, which could be as simple as destructuring the array before sorting it:

return [...list].sort(compare);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading