Обратный вызов setState не ожидает обновления состояния

У меня есть этот фрагмент кода:

    handleMaxLevel = event => {
    this.setState({
      maxLevel: event.target.value
    }, (minLevel, maxLevel) => {
      let filter = this.state.filteredPlayers.filter(players => {
        return players.level > minLevel && players.level < maxLevel
      })
      this.setState({
        levelFilteredPlayers: filter
      })
    })
  }

Я вызываю эту функцию в этом фрагменте кода:

 <TextField
        id = "standard-number"
        label = "Highest level"
        type = "number"
        onChange = {() => this.handleMaxLevel(this.state.minLevel, this.state.maxLevel)}
        InputLabelProps = {{
          shrink: true,
        }}
  />

Что я получаю: TypeError: Невозможно прочитать значение свойства undefined
Пишет, что проблема в этой строке: maxLevel: event.target.value.
Я не понимаю, разве обратный вызов не должен ждать завершения первого setstate, чтобы он выполнялся? Почему он не восстанавливает значение, установленное в состояние maxLevel?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
97
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваш синтаксис неверен. Когда вы вызываете handleMaxLevel, вы должны передавать ему объект события. А обратному вызову setState не нужны никакие аргументы, он уже имеет доступ к обновленному состоянию. Итак, ваш обработчик onChange должен быть таким:

onChange = {handleMaxLevel} // If we pass function directly, it will be given the event argument by default

а затем в обратном вызове setState обратитесь непосредственно к значениям состояния, так как в обратном вызове они будут обновлены:

handleMaxLevel = event => {
    this.setState({
        ...this.state,
        maxLevel: event.target.value
    }, () => {
        let filter = this.state.filteredPlayers.filter(players => {
            return players.level > this.state.minLevel && players.level < this.state.maxLevel
        })
        this.setState({
            ...this.state,
            levelFilteredPlayers: filter
        })
    })
}

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

Что здесь не так, так это то, что ваша функция ожидает один аргумент

const handleMaxLevel = event => {
// ...
}

но ваш вызов отправляет два аргумента

onChange = {() => this.handleMaxLevel(this.state.minLevel, this.state.maxLevel)}

Если вы хотите изменить свою функцию, чтобы принимать переменные событий и переменных состояния:

// Change invocation like so:
onChange = {event => this.handleMaxLevel(event, this.state.minLevel, this.state.maxLevel)}

// Change function definition like so:
const handleMaxLevel = (event, minLevel, maxLevel) => {
// ...
}

но, поскольку вы просто используете атрибуты состояния внутри функции, вам даже не нужно передавать их явно:

onChange = {e => this.handleMaxLevel(e)}

это позволит вам сделать вашу функцию такой:

const handleMaxLevel = event => {
    // access state attributes like this:
    const {minLevel, maxLevel} = this.state;
    // and now you also have access to the event value
    this.setState({ maxValue: e.target.value });
}

Другие вопросы по теме