Как setState в React работает в этом сценарии?

Я пытаюсь установить состояние объекта в моем массиве. Я достиг этого, но я не понимаю этого.

toggleVisited = countryCode => {
  var countries = [ ...this.state.countries ];
  var countryToChange = countries.find(country => country.code === countryCode);
  countryToChange.visited = !countryToChange.visited;
  this.setState({ countryToChange });
}

Я понимаю (в основном), что происходит, до последнего this.setState линия.

Я изменил код на this.setState({}) и это все еще работало. Я всегда думал, что set state устанавливает новое значение для ключа объекта. Почему (независимо от того, что я вставил сюда), он все еще правильно настраивает?

3 ответа

Решение

С countryToChange.visited = !countryToChange.visited, вы мутируете своим текущим состоянием. Не делай этого. Вместо этого создайте новый объект:

toggleVisited = countryCode => {
    this.setState(prevState => {
        const countries = prevState.countries.map(country => country.code !== countryCode
            ? country
            : {
                ...country,
                visited: !country.visited
            })
        const countryToChange = countries.find(country => country.code === countryCode)

        return {
            countries,
            countryToChange
        }
    })
}
toggleVisited = countryCode => {
  var countries = [ ...this.state.countries ];
  //here you use spread operator to "clone" all countries
  var countryToChange = countries.find(country => country.code === countryCode);
  //you filter all your countries and get the one with the CC you want
  countryToChange.visited = !countryToChange.visited;
  //your country is an object, and you change visited prop to it's opposite
  //boolean, !false == true
  this.setState({ countryToChange });
  //you just changed your country visited prop, in react you cannot change
  //deep props so, you re-set {countryToChange: countryToChange}
  //or simply {countryToChange} due to new ES features
}

Состояние компонента React должно рассматриваться как неизменяемое, но вы можете изменить его значения. Ваш код будет работать для каждого setState(), который вы делаете, потому что setState запускает повторный рендеринг, и так как вы уже изменили состояние countryToChange.visited = !countryToChange.visited;, компонент будет перерисован с новым состоянием.

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