单击两次时如何从状态切换排序数组数据?

时间:2019-03-21 17:44:24

标签: javascript reactjs

创建了多个功能,可按点击率按等级,股票和标题排序。如果可能的话,我想做的是按实例“切换”电影标题ASC顺序并第二次单击“ DESC”。尝试创建默认的布尔值isSorted: false,并根据点击设置将isSorted设置为true,如果是,则将其从B排序为A。

我在React上工作了1个月,如果有人能给我一些积极的反馈意见,使我在React上变得更好,我将不胜感激。

我的React代码:

import React, { Component } from 'react';

import { getMovies } from '../services/fakeMovieService';

class Movies extends Component {
    state = {
        isSorted: false,
        movies: getMovies(),
        isDisabled: true,
    };

    // Display all movies but not the one selected.
    handleDelete = movie => {
        this.setState({
            movies: this.state.movies.filter(m => m._id !== movie._id),
            isDisabled: false,
        });

        console.log(`Movie ${movie.title} deleted.`);
    };

    // Sort all video's by title
    sortByTitle = () => {
        this.setState({
            movies: this.state.movies.sort((a, b) =>
                a.title > b.title ? 1 : -1
            ),
            isDisabled: false,
        });

        console.log('sorted by title');
    };

    // Sort all video's by genre
    sortByGenre = () => {
        this.setState({
            movies: this.state.movies.sort((a, b) =>
                a.genre.name > b.genre.name ? 1 : -1
            ),
            isDisabled: false,
        });
        console.log('sorted by genre.');
    };

    // sort all video's by stock size
    sortByStock = () => {
        this.setState({
            movies: this.state.movies.sort(
                (a, b) => a.numberInStock - b.numberInStock
            ),
            isDisabled: false,
        });

        console.log('sorted by stock size.');
    };

    // Sort all video's by rating score
    sortByRating = () => {
        this.setState({
            movies: this.state.movies.sort(
                (a, b) => a.dailyRentalRate - b.dailyRentalRate
            ),
            isDisabled: false,
        });

        console.log('sorted by rating sore.');
    };

    // Add class to the reset button based on the current filter state.
    resetButtonClass = () => {
        let btnClass = 'btn btn-sm btn-';
        btnClass += this.state.isDisabled ? 'warning' : 'primary';
        return btnClass;
    };

    // Reset the video's filter
    resetFilter = () => {
        this.setState({
            movies: [...getMovies()],
            isDisabled: true,
        });

        console.log('Reset movies database.');
    };

    render() {
        const { length: count } = this.state.movies;

        // Check if there are movies available.
        if (count === 0)
            return (
                <React.Fragment>
                    <h4>There are no movies in the database.</h4>
                    <button
                        type="button"
                        onClick={this.resetFilter}
                        className="btn btn-primary btn-sm">
                        Reset
                    </button>
                </React.Fragment>
            );

        return (
            <React.Fragment>
                <h5 className="pb-2">Showing {count} in the database.</h5>
                <table className="table table-striped table-dark">
                    <thead>
                        <tr>
                            <th onClick={this.sortByTitle}>Title</th>
                            <th onClick={this.sortByGenre}>Genre</th>
                            <th onClick={this.sortByStock}>Stock</th>
                            <th onClick={this.sortByRating}>Rate</th>
                            <th scope="col">
                                <button
                                    onClick={this.resetFilter}
                                    className={this.resetButtonClass()}
                                    disabled={this.state.isDisabled && true}>
                                    Reset filter
                                </button>
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        {this.state.movies.map(movie => {
                            const {
                                _id,
                                title,
                                genre,
                                numberInStock,
                                dailyRentalRate,
                            } = movie;

                            return (
                                <tr key={_id}>
                                    <th>{title}</th>
                                    <td>{genre.name}</td>
                                    <td>{numberInStock}</td>
                                    <td>{dailyRentalRate}</td>
                                    <td>
                                        <button
                                            onClick={() =>
                                                this.handleDelete(movie)
                                            }
                                            className="btn btn-danger btn-sm">
                                            Delete
                                        </button>
                                    </td>
                                </tr>
                            );
                        })}
                    </tbody>
                </table>
            </React.Fragment>
        );
    }
}

export default Movies;

P.S。 我的代码干净且易于理解吗?

谢谢。

关于, 尼诺

3 个答案:

答案 0 :(得分:0)

您可以这样做

这里的想法是基于sorted键的值,我们设置sort函数的返回值,然后切换sort键的值

let obj = {
  data: [5,4,3,2,1,0],
  sorted: 'dsc'
}

// let first click  happended

obj.data.sort((a,b)=> obj.sorted === 'asc' ? b-a : a-b)
obj.sorted = obj.sorted === 'asc' ? 'dsc' : 'asc'

console.log(obj.data)

// let second click  happended

obj.data.sort((a,b)=> obj.sorted === 'asc' ? b-a : a-b)
obj.sorted = obj.sorted === 'asc' ? 'dsc' : 'asc'
console.log(obj.data)

答案 1 :(得分:0)

您可以调整sortByTitle方法来更改isSorted的值,然后有条件地对其进行升序或降序排序。

sortByTitle = () => {
        let movies = this.state.movies
        let isSorted = !this.state.isSorted

        if (!this.state.isSorted){
            movies = movies.sort((a, b) =>
                a.title > b.title ? 1 : -1
            )
        } else {
            movies = movies.sort((a, b) =>
                a.title > b.title ? -1 : 1 
            )
        }

        this.setState({
            isDisabled: false,
            movies, isSorted
        });

        console.log('sorted by title');
    };

答案 2 :(得分:0)

您应在状态下存储尽可能少的数据。您无需将电影存储在状态中,因为您始终可以从getMoviesisSortedisDisabled计算电影:

function computeMovies(sort, isDisabled) {
   switch(sort) {
       case 'TITLE_ASC':
          return getMovies().sort(....);
       case 'TITLE_DESC':
          return getMovies().sort(....);
       ... more cases here
   }
}

render() {
   const movies = computeMovies(this.state.sort, this.state.isDisabled);

   return ...
}

将排序逻辑放在纯函数中可以更轻松地进行测试和推理。

应用相同的原理来设置sort

function computeSort(sort) {
   switch(state) {
      case 'TITLE_ASC':
         return 'TITLE_DESC'
     ... more cases here
   }
}
 sort = (sortProp) => {
    switch(sortProp) {
       case 'TITLE':
         this.setState({
            sort: this.state.sort === 'TITLE_ASC' ? 'TITLE_DESC' : 'TITLE_ASC';
         });
       ... more cases here
    }
 }


 render() {
 <th onClick={ () => this.sort('TITLE')}>Title</th>