preface

Recently, when using THE TABLE component of ANTD, I found some problems with the sorting function of version 3.10.0.

It has been officially fixed in a later version.

  • Fixed an issue where unsorted column headers trigger sorting when clicked. # 12515

But for a variety of reasons can only be solved by themselves, after consulting the document found using the version of the title support function to customize, so that custom sorting is possible. At the same time to meet the requirements of click icon sort, icon to restore the default function.

Analyze requirements

First, analyze the requirements:

  • Add a column to the columnssortTo identify the columns that need to be sorted
  • defineonSortChangeFunction to handle sorting changes
  • containssortThe column of the field passestitleIs replaced with a custom sorting component
  • The columns in thetitlePass in the custom sorting component directly
  • Consider clearing sorted scenarios, such as a table with a search function, and request parameter changes.

Encapsulating table components

Create tableComp file (tableComp file)

import React, { useMemo } from 'react';
import { Table } from 'antd';
// Customize the sorting component
import Sorter from './sorter'

export default ({
    columns,
    sortClear,
    onSortChange=() = >{},
    ...tableProps
})=>{
    
    // Handle the sort of columns passed by the parent component
    const cols=useMemo(() = >{
        return columns.map(col= >{
            if(col.sort){
                const{ title, sort, ... colProps }=col col={ ... colProps,title:() = >(
                        <Sorter
                            title={title}
                            field={colProps.dataIndex}
                            onChange={onSortChange}
                            clear={sortClear} 
                        />)}}return col
        })
    },[columns,sortClear])
    
    return (
        <Table 
            columns={cols}// Use processed columns for presentation
            {. tableProps}
            pagination={false}
        />)}Copy the code

Custom sorting componentsSorter

Analysis:

  • Two ICONS are required, directly using ANTDIcon
  • Click the corresponding icon to triggeronChangeEvent, and passed in{field:' descend ',order:' descend ', ascend, descend, descend '}
  • Consider the ability to clear sorts
import React, { useState,useEffect } from 'react';
import {Icon} from 'antd'

import './sorter.css'

export default ({
    title,
    field,
    onChange=() = >{},
    clear
})=>{
    const [order,setOrder]=useState()

    // Use onClick on multiple elements and prevent bubbling, or use an event and determine which DOM element is triggered
    const handleSortClick=(ord,e) = >{
        e.stopPropagation()
        if(order! ==ord){ setOrder(ord) onChange({field,order:ord})
        }
    }

    useEffect(() = >{
        if(clear){
            setOrder()
        }
    },[clear])

    // The outermost click is used to unsort
    return (
        <div
            className="sorter"
            onClick={handleSortClick.bind(null,undefined)}
        >
            <div className="sorter_title">{typeof title==='function'? title():title}</div>
            <div className="sorter_icon">
                <Icon 
                    className={order= = ='ascend'&& 'active'}
                    type="caret-up"
                    onClick={handleSortClick.bind(null,'ascend')} / >
                <Icon 
                    className={order= = ='descend'&& 'active'}
                    type="caret-down"
                    onClick={handleSortClick.bind(null,'descend')} / >
            </div>
        </div>)}Copy the code

Style modification:

.sorter{
    display: flex;
    align-items: center;
}

.sorter_title{
    white-space: nowrap;
}

.sorter_icon{
    display: flex;
    flex-direction: column;
    color: #dfdfdf;
    max-width: 100%;
    min-width: 12px;
    overflow: hidden;
    margin-left: 5px;
}

.anticon{
    transition: 0.3 s;
    cursor: pointer;
}

.anticon.active{
    color: #000ab2;
}
Copy the code

At this point, the functionality is basically implemented, but the requirement is single-column sorting.

Implement a single column sort

When switching between columns, clear the sorting effect of other columns:

  • Record the current sequence in the tablesortField
  • Only in column names withsortFieldDisplay sorting effects in the same sorting component
export default ({
    columns,
    sortClear,
    onSortChange=() = >{},
    ...tableProps
})=>{
    / / sequence
    const [sortField,setSortField]=useState()
    
    // Retrieve the change function to record the current sequence
    const handleSortChange=useCallback((sortData={}) = >{
        setSortField(sortData.field)
        onSortChange(sortData)
    },[onSortChange])
    
    const cols=useMemo(() = >{
        return columns.map(col= >{
            if(col.sort){
                const{ title, sort, ... colProps }=col col={ ... colProps,title:() = >(
                        <Sorter
                            title={title}
                            field={colProps.dataIndex}
                            onChange={handleSortChange}// Not cleared at the same time as the current columnclear={sortClear || sortField! = =colProps.dataIndex} 
                        />)}}return col
        })
    },[columns, handleSortChange, sortClear, sortField])
    
    return (
        <Table 
            columns={cols}
            {. tableProps}
            pagination={false}
        />)}Copy the code

At this point, all the questions raised by the requirements have been completed.

The effect

Finally, look at the effect