Change position of arrow icon based on sort

Hi my sorting is done via the backend, I need to reflect it in the UI with React.

I’m looking to achieve this:

  1. Arrow position is defaulted to pointing down when page loads (no sort is occurring at this stage)
  2. Click on Arrow this will point upwards sorting table results as ascending
  3. Click on Arrow again this will point downwards sorting table results as descending

Right now my code does this:

  1. Arrow position is defaulted to pointing upwards when page loads

  2. Click on Arrow it changes to down arrow and sorts table results as descending

  3. Click on Arrow again it changes to upwards and sorts table results as ascending

    import React, { useState, useEffect } from 'react';
    import PropTypes from 'prop-types';
    import styled from 'styled-components';
    import { FaIcon } from './icons';
    
    const HeaderWrapper = styled.div`
      width: 100%;
      display: flex;
      justify-content: space-between;
      align-items: center;
    `;
    
    const Div = styled.div`
      font-weight: bold;
    `;
    const Icon = styled(FaIcon)`
      font-size: 16px;
    `;
    
    const TableHeader = ({ title, field, getSortedJobs }) => {
      const [ascending, setAscending] = useState(null);
    
      const nullCheck = () => {
        if (!ascending) return 'desc';
        if (ascending === 'asc') return 'desc';
        return 'asc';
      };
    
      const positionArrow = () => {
        if (!ascending) return ['far', 'chevron-up'];
        if (ascending === 'asc') return ['far', 'chevron-up'];
        return ['far', 'chevron-down'];
      };
    
      const sortBy = () => {
        setAscending(nullCheck());
      };
    
      useEffect(() => {
        if (ascending) getSortedJobs(field, ascending);
      }, [ascending]);
      return (
        <HeaderWrapper onClick={() => sortBy()}>
          <Div>{title}</Div>
          <Icon icon={positionArrow()} />
        </HeaderWrapper>
      );
    };
    
    TableHeader.propTypes = {
      title: PropTypes.string,
      field: PropTypes.array,
      getSortedJobs: PropTypes.func,
    };
    
    TableHeader.defaultProps = {
      title: '',
      field: [],
      getSortedJobs: () => {},
    };
    
    export default TableHeader;
    

Answer

Untested, but I think you’ll need to change this line in function positionArrow:

if (!ascending) return ['far', 'chevron-up'];

to:

if (!ascending) return ['far', 'chevron-down'];

since ascending will be null/falsey and you want the arrow to be pointing down to begin with.


Then I think you should also change this line in function nullCheck:

if (!ascending) return 'desc';

to:

if (!ascending) return 'asc';

since ascending will the null/falsey to begin with (i.e. desc initially) and so the next value needs to be asc.


Sidenote: Since you want the same behaviour for when ascending is null or desc, you could also re-write the functions as:

const positionArrow = () => {
  return ['far', 'asc' === ascending ? 'chevron-up' : 'chevron-down'];
};

const sortBy = () => {
  setAscending(prev => 'asc' === prev ? 'desc' : 'asc');
};

This would also allow you to get rid of function nullCheck (if you’re not using it anywhere other than sortBy).

Leave a Reply

Your email address will not be published. Required fields are marked *