Solution 1 :

It’s better to use the setState overload that takes a function instead of the object.

Here is a simple example.

class Sample extends React.Component {

  constructor() {
    super();
    this.initData = [
        {name: 'John', family: 'Doe'},
        {name: 'Jane', family: 'Hardy'}
      ];
    this.state = {
      sortField: 'name',
      sortOrder: 'asc',
      data: this.initData
    };
  }

    sort(column) {
        this.setState(prevState => {
            if (prevState.sortField === column) {
                const sortOrder = prevState.sortOrder === 'asc' ? 'desc' : 'asc';

                return {
                    sortOrder,
                    data: [...prevState.data].sort((a, b) => {
                        const textA = a[column].toUpperCase();
                        const textB = b[column].toUpperCase();
                        if (sortOrder === 'asc') {
                            return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
                        }
                        else {
                            return (textA > textB) ? -1 : (textA < textB) ? 1 : 0;
                        }
                    })
                }
            }
            else {
                return {
                    sortOrder: 'asc',
          sortField: column,
                    data: [...prevState.data].sort((a, b) => {
                        const textA = a[column].toUpperCase();
                        const textB = b[column].toUpperCase();
                        return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
                    })
                }
            }
        })
    }

  render() {
     return (
       <table>
         <thead>
           <th onClick={() => this.sort('name')}>Name</th>
           <th onClick={() => this.sort('family')}>Family</th>
         </thead>
         <tbody>
           {
             this.state.data.map(({name, family}, i) => {
               console.log(name, family)
               return (
                 <tr key={i}>
                   <td>{name}</td>
                    <td>{family}</td>
                 </tr>
               )
             })
           }
         </tbody>
       </table>
     )
  }
}

React.render(<Sample />, document.getElementById('app'));

Problem :

I have a problem with sorting state.

I would like to set column sorting as ascending every time when I change the selection of my column and change state as “asc” then “desc” etc.

When I clicking on the same column. Method getHeaderName get actually selected header name and it works properly. Method sortedMethod
just have sorting mechanism(works good) and set state of column name previously selected and actually selected:

private sortedMethod(columnName: HeaderNameDictionary) {
  this.sortedMechanism(columnName);
  this.setState({ previousColumn: this.state.sortedColumnName })
  this.setState({ sortedColumnName : columnName})
}

I think that the problem is with the method “setStateSelectedColumn”. In this method, I check the state of current and previous column names and depend on it I set “isAscending” state. But it does not work well.

private setStateSelectedColumn(columnName: HeaderNameDictionary) {
  if ((this.state.previousColumn !== this.state.sortedColumnName )) {
    this.setState({ isAscending: true })
  } else {
    this.setState({ isAscending: !this.state.isAscending })
  }
}

When I change column and click every time on another column it works good and
change state as isAsc: true,
but when I :
change column – isAsc: true,
Click one more time on this column – isAsc: true,
Click one more time on this column – is Asc: false,
Click one more time on this column – is Asc: true,
Click one more time on this column – is Asc: false,

Second clicking on the same column is problematic and does not change the state.

<th>
  Product Code
  <span
    className={this.getHeaderName(HeaderNameDictionary.PRODUCT_CODE)}
    onClick={() => {
      this.setState({}, () => {
        this.setStateSelectedColumn(HeaderNameDictionary.PRODUCT_CODE);
      });
      this.sortedMethod(HeaderNameDictionary.PRODUCT_CODE);
    }}
  />
</th>;

Do you have any idea how to fix this? Thanks!

Comments

Comment posted by Pol Pol

Yes I used set state that takes a function: this.setState({}, () => { this.setStateSelectedColumn(HeaderNameDictionary.PRODUCT_CODE); });

By