Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort the data in asc and desc order in table

I am new to react js. Here, I am trying to sort the data when the user clicks on the icons.

<th scope="col">Technology <i className="fa fa-fw fa-sort sort-icon"></i></th>

So, Now I have data which is in the form of an array of objects.

In this, I have 5 columns and sort icon is on every column. So, How do I Implement this thing using the react?

I want to sort using the alphabetical order.

My data looks like,

[{
        "id": "5b7d4a566c5fd00507501051",
        "hrmsJdId": null,
        "companyId": null,
        "jdName": "Senior/ Lead UI Developer",
        "jobDescription": null,
        "technology": java,
    }, {
        "id": "5b7fb04d6c5fd004efdb826f",
        "hrmsJdId": null,
        "companyId": null,
        "jdName": "Content Innovation Lead",
        "jobDescription": null,
        "technology": css
    }, {
        "id": "5b7fb0b26c5fd004efdb8271",
        "hrmsJdId": null,
        "companyId": null,
        "jdName": "Urgent Opening for DSP Engineer/ Senior Engineer for",
        "jobDescription": null,
        "technology": react,
    }]

 <td>{item.technology}</td>
                <td>17</td>
                <td title={item.jdName} className="jd-name-container justify-content-center align-items-center">
                  <div className="jdName">{item.jdName}</div>
                  {(key + 1 === 1) && <div className="badge new-badge badge-warning-custom">New</div>}
                </td>

This is how I render the data. Now,

By default, I sort it using the

   <tbody className="text-center">
          {props.jobList && props.jobList && props.jobList.length > 0 && props.jobList.sort((a, b) => b.createdAt - a.createdAt).map((item, key) => {
            return (
              <tr key={key}>
                <td align="center"> <input type="checkbox" name="myTextEditBox" value="checked" /></td>
                <td>{item.technology}</td>
                <td>17</td>
                <td title={item.jdName} className="jd-name-container justify-content-center align-items-center">
                  <div className="jdName">{item.jdName}</div>
                  {(key + 1 === 1) && <div className="badge new-badge badge-warning-custom">New</div>}
                </td>
                <td>30</td>
                <td>30</td>
                <td>
 </tbody>

So, How do I implement this ?

What I did is ,

<th scope="col">Technology<i className="fa fa-fw fa-sort sort-icon" onClick={props.sortAscending('Technology')}></i></th>

then in container

    sortData = (key,event) => {
        console.log("key is,", key);
        this.props.sortAscending(key);
      }

<UserJobsTabel jobList={filteredList} sortAscending={this.sortData} />

passed as a props.

Now in action,

export const sortAscending = (type) => {
  return {
    type: "SORT_ASCENDING",
    payload: type
  }
}

In reducer,

case FETCHING_JOBDESCRIPTION_SUCCESS:
            return {
                ...state,
                jobList: action.data.jobData ? action.data.jobData.sort((a, b) => b.createdAt - a.createdAt) : action.data.jobData,
                yesterDayScore: action.data.yesterdayScore,
                todayScore: action.data.todayScore,
                error: false,
            }

 case "SORT_ASCENDING": 
          const { sortKey } = action.payload;
            const jobList = [ ...state.jobList ]
        .sort((a, b) => a[sortKey].localeCompare(b[sortKey]));
      return { ...state, jobList };

×

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

I am getting this error.

like image 596
ganesh Avatar asked Mar 05 '19 05:03

ganesh


2 Answers

Use localeCompare() to sort in alphabetical order.

Have the sorting done in reducer while the component just dispatches the "sort" action. Every re-sort will cause a component re-render for jobList prop (in mapStateToProps) is updated.

In reducer:

const initialState = {
  jobList: [],
};

export const jobList = (state = initialState, action) => {
  switch(action.type) {
    case Action.SORT_ALPHA_ASC:
      const { sortKey } = action.payload;
      const jobList = [ ...state.jobList ]
        .sort((a, b) => a[sortKey].localeCompare(b[sortKey]));

      return { ...state, jobList };

    default:
      return state;
  }
}

In your component:

// alphaSort will dispatch action: SORT_ALPHA_ASC
const { jobList, alphaSort } = this.props;
if (! jobList || jobList.length < 1) {
  // no job list
  return null;
}

return (
<table>
  <thead>
    { /* TODO: use th/td */ }
    <SomeIcon name='asc-technology' onClick={() => alphaSort('technology')} />
    <SomeIcon name='asc-jdname' onClick={() => alphaSort('jdName')} />
    { /* TODO: other fields */ }
  </thead>
  <tbody>
  {
    jobList.map((job) => ({
      <tr key={job.id}>
        <td name="technology">{job.technology}</td>
        <td title={job.jdName}>
          <div className="jdName">{job.jdName}</div>
        </td>
        { /* TODO: other fields */ }
      </tr>
    }))
  }
  </tbody>
</table>
);

NOTE: descending alpha sort and other fields will be for the OP to continue. :)

like image 69
Joseph D. Avatar answered Sep 27 '22 19:09

Joseph D.


React Js arrays have a sort function:

['b', 'a'].sort((e1, e2) => e1.id < e2.id  ? 1 : - 1)

If the lambda function returns 0, it does nothing. Otherwise, the two elements in the array will be sorted by the sign of the returned value.

If there are duplicate IDs in the database then the function will return 0.

To swap the order, change either the sign of the return value or the "smaller than" operator to a greater than operator.

like image 42
tomitheninja Avatar answered Sep 27 '22 21:09

tomitheninja