Почему контент сортируется по неправильному варианту? - PullRequest
0 голосов
/ 03 июня 2018

Итак, я получаю информацию о фильме из API.На моей странице у меня есть три варианта в выпадающем меню для сортировки по алфавиту, количеству пользователей и популярности.

Проблема в том, что когда я выбираю опцию, она сортирует по опции перед ней.Например, когда я выбираю сортировку по пользовательскому баллу, он сортирует по алфавиту, что является опцией перед ним в раскрывающемся списке.И потом, если я продолжу выбирать варианты, они в конечном итоге станут случайными и будут сортироваться с любым из них.

Не уверен, почему это происходит.Я предполагаю, что это как-то связано с тем, как я устанавливаю состояние.

Вот мой код:

import React, {Component} from "react";
import {connect} from "react-redux";
import {crimeGenre} from "./redux";

class CrimeGenre extends Component {
    constructor(){
        super();

        this.state = {
            value: "alphabetically"
        }
    }

    componentDidMount(){
        this.props.crimeGenre();
    }

    sortFilms = (event) => {
        this.setState({
            value: event.target.value
        })
        if(this.state.value === "alphabetically"){
            return this.props.select && this.props.select.sort((a, b) => {
                return a.title < b.title ? -1 : 1;
            });
        }else if(this.state.value === "score"){
            return this.props.select && this.props.select.sort((a, b) => {
                return a.vote_average > b.vote_average ? -1 : 1;
            });
        }else if(this.state.value === "popularity"){
            return this.props.select && this.props.select.sort((a, b) => {
                return a.popularity > b.popularity? -1 : 1;
            });
        }
    }

    render(){
        const mappedSelected = this.props.select && this.props.select.map((film, i) => { 
            return (
                <div key={i}>
                    <h1>{film.title}</h1>
                    <img src={`http://image.tmdb.org/t/p/w185${film.poster_path}`}/>
                    <p>Avg. User Score: {film.vote_average}</p>
                    <p>Popularity Index: {film.popularity.toFixed(0)}</p>
                </div>
            )
        })

            return(
                <div>
                <form>
                    <label>
                        Sort By:
                        <select value={this.state.value} onChange={this.sortFilms}>
                            <option id="alphabetically" value="alphabetically">Alphabetically</option>
                            <option id="score" value="score">User Score</option>
                            <option id="popularity" value="popularity">Popularity</option>
                        </select>
                    </label>
                </form>
                    {mappedSelected}
                </div>
            )
        }
    }

export default connect(state=> state, {crimeGenre})(CrimeGenre);

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Есть пара вещей, которые вам нужно изменить

Сначала используйте выбранную опору, чтобы установить начальное состояние, например

 constructor(props){
        super(props);
        this.state = {
            value: "alphabetically",
            select: props.select
           }
        } 

Вы хотите сделать это, потому что хотите вызватьповторять визуализацию всякий раз, когда выбираются изменения (или изменения их порядка), поэтому он относится к состоянию вашего компонента.

Теперь, когда вы переходите к вашей функции sortFilm, установите состояние после того, как вы отсортировали значения, такие как:

sortFilms = event => {
  const sorter = event.target.value;
  const films = this.state.select;
  if (sorter === "alphabetically") {
    films.sort((a, b) => {
      return a.title < b.title ? -1 : 1;
    });
  } else if (sorter === "score") {
    films.sort((a, b) => {
      return a.vote_average > b.vote_average ? -1 : 1;
    });
  } else if (sorter === "popularity") {
    films.sort((a, b) => {
      return a.popularity > b.popularity ? -1 : 1;
    });
  }
  //Now we set the state to cause the re-render
  this.setState({ value: sorter, select: films });
};

И, наконец, чтобы использовать наше состояние, которое меняется всякий раз, когда мы подаем файл, мы будем использовать наше состояние вместо реквизитов, как

const mappedSelected = this.state.select && this.state.select.map((film, i) => { 
            return (
                <div key={i}>
                    <h1>{film.title}</h1>
                    <img src={`http://image.tmdb.org/t/p/w185${film.poster_path}`}/>
                    <p>Avg. User Score: {film.vote_average}</p>
                    <p>Popularity Index: {film.popularity.toFixed(0)}</p>
                </div>
            )
        })

Теперь перейдем к проблеме с вашим кодом:

Вы устанавливаете состояние, которое вызывает рендеринг и является асинхронным, поэтому, когда вы изменяете свои реквизиты путем их сортировки, компонент не может знать, что реквизиты изменены.Таким образом, если когда-либо будет вызван следующий повторный рендеринг, компонент обновляется и начинает использовать новые реквизиты, Это начинает работать случайным образом, когда вы начинаете быстро менять фильтры, так как он меняет реквизиты несколько раз, даже до того, как состояние установлено.

Код из AndrewL завершается сбоем по той же причине, он устанавливает состояние и вызывает повторную визуализацию, а затем меняет реквизиты, у компонента нет новой реквизита, чтобы обновлять себя там.

0 голосов
/ 03 июня 2018

React setState() не сразу отражает обновление значения состояния, но создает ожидающий переход состояния.Доступ к состоянию после вызова setState() потенциально может вернуть существующее значение.

Нет гарантии синхронной обработки вызовов на setState, и вызовы могут быть сгруппированы для увеличения производительности.

ПроверкаИз официальных ReactJS Docs , которые объясняют это лучше.


Чтобы убедиться, что ваша sortFilms функция использует новое состояние, передайте ее как обратный вызов setState(), например так:

sortFilms = (event) => {
    this.setState({value: event.target.value}, function () {
        if(this.state.value === "alphabetically"){
            return this.props.select && this.props.select.sort((a, b) => {
                return a.title < b.title ? -1 : 1;
            });
        }else if(this.state.value === "score"){
            return this.props.select && this.props.select.sort((a, b) => {
                return a.vote_average > b.vote_average ? -1 : 1;
            });
        }else if(this.state.value === "popularity"){
            return this.props.select && this.props.select.sort((a, b) => {
                return a.popularity > b.popularity? -1 : 1;
            });
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...