Ivana
Ivana

Reputation: 842

Sorting React table by clicking table headers for columns with numerical and string values

I am having problems in sorting my React table by clicking on columns headers for column with string values, but with the column with numerical values it's all ok. I think that I am doing wrong in sortBySymbolHandler method. I suppose that my check for strings: this.state.directionSymbol[key] === 'asc'? a[key] - b[key] : b[key] - a[key] is wrong.

    import React, { Component } from 'react';
    import CoinTable from '../components/CoinTable/CoinTable';
    import data from '../components/Data/Data.json';

    class App extends Component {
        constructor(props) {
            super(props)
            this.state = {
                data: data,
                direction: {
                    price_usd: 'asc'
                },
                directionSymbol: {
                    symbol: 'asc'
                }
            }
        }

        sortBySymbolHandler = (key) => {
             this.setState({
                data: data.sort((a, b) => (
                    this.state.directionSymbol[key] === 'asc'
                    ? a[key] - b[key]
                    : b[key] - a[key]
                )),

                directionSymbol: {
                    [key]: this.state.directionSymbol[key] === 'asc'
                    ? 'desc'
                    : 'asc'
                }
            })
        }

        sortByPriceHandler = (key) => {
            this.setState({
                data: data.sort((a, b) => (
                    this.state.direction[key] === 'asc'
                    ? 
                     parseFloat(a[key]) - parseFloat(b[key])
                    : parseFloat(b[key]) - parseFloat(a[key])
                )),

                direction: {
                    [key]: this.state.direction[key] === 'asc'
                    ? 'desc'
                    : 'asc'
                }
            })
        }

        render() {
            return (
                <div className="App">
                    <div className="container-fluid">
                        <div className="container">
                            <CoinTable 
                                data={this.state.data} 
                                sortBySymbol={this.sortBySymbolHandler}
                                sortByPrice={this.sortByPriceHandler}
                            />
                        </div>
                    </div>
                </div>
            );
        }
    }

    export default App;

Data.json is in this format:

    [
        {
            "id": "bitcoin", 
            "name": "Bitcoin", 
            "symbol": "BTC", 
            "rank": "1", 
            "price_usd": "10406.5", 
            "price_btc": "1.0", 
            "24h_volume_usd": "9766700000.0", 
            "market_cap_usd": "175053324790", 
            "available_supply": "16821537.0", 
            "total_supply": "16821537.0", 
            "max_supply": "21000000.0", 
            "percent_change_1h": "-0.04", 
            "percent_change_24h": "-3.39", 
            "percent_change_7d": "-12.62", 
            "last_updated": "1516718960"
        }, 
        {
            "id": "ethereum", 
            "name": "Ethereum", 
            "symbol": "ETH", 
            "rank": "2", 
            "price_usd": "947.841", 
            "price_btc": "0.0917641", 
            "24h_volume_usd": "3615420000.0", 
            "market_cap_usd": "92093645501.0", 
            "available_supply": "97161492.0", 
            "total_supply": "97161492.0", 
            "max_supply": null, 
            "percent_change_1h": "0.3", 
            "percent_change_24h": "-4.04", 
            "percent_change_7d": "-13.22", 
            "last_updated": "1516718952"
        }, 
        {
            "id": "ripple", 
            "name": "Ripple", 
            "symbol": "XRP", 
            "rank": "3", 
            "price_usd": "1.27202", 
            "price_btc": "0.00012315", 
            "24h_volume_usd": "2597960000.0", 
            "market_cap_usd": "49276964438.0", 
            "available_supply": "38739142811.0", 
            "total_supply": "99993093880.0", 
            "max_supply": "100000000000", 
            "percent_change_1h": "0.83", 
            "percent_change_24h": "3.49", 
            "percent_change_7d": "-5.9", 
            "last_updated": "1516718941"
        } 
]

and CoinTable.js is like this:

import React from 'react';;
import TableRow from './TableRow/TableRow';

const coinTable = (props) => (
    <table>
        <thead>
            <tr>
                <th>#</th>
                <th>Name</th>
                <th><button onClick={() => props.sortBySymbol('symbol')}>Symbol</button></th>
                <th><button onClick={() => props.sortByPrice('price_usd')}>Price</button></th>
                <th>%/hour</th>
                <th>%/day</th>
                <th>%/week</th>
            </tr>
        </thead>
        <tbody>
            {
                props.data.map(row => {
                    const price = row.price_usd;
                    const formattedPrice = parseFloat(price).toFixed(2);
                    return (
                        <TableRow key={row.rank} row={row} formattedPrice={formattedPrice} />
                    )
                })
            }
        </tbody>
    </table>
);

export default coinTable;

Can somebody help?

Upvotes: 2

Views: 9241

Answers (1)

Doug Coburn
Doug Coburn

Reputation: 2575

You can't subtract one string from another string.

Instead of doing:

 data: data.sort((a, b) => (
     this.state.directionSymbol[key] === 'asc'
         ? a[key] - b[key]
         : b[key] - a[key]
 )),

Do:

 data: data.sort((a, b) => {
     const asc = this.state.directionSymbol[key] === 'asc';
     if (a[key] < b[key]) {
         return asc ? -1 : 1;
     } else if (a[key] > b[key]) {
         return asc ? 1 : -1;
     } else {
         return 0;
     }
 )),

Upvotes: 1

Related Questions