Форум программистов, компьютерный форум, киберфорум
React/ReactJS
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
38 / 14 / 4
Регистрация: 28.01.2020
Сообщений: 170

Как работает setState()?

04.04.2021, 21:57. Показов 1647. Ответов 8

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Поясните, пожалуйста как работает метод setState() в данном коде.

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import React from "react";
import ReactDOM from "react-dom";
 
const UNIT = {
  KPH: 'Км/ч',
  MPH: 'Миль/ч'
};
 
// максимальная разрешённая скорость в населённом пункте в км/ч
const MAX_SPEED_IN_CITY_IN_KPH = 60
 
function SpeedDetector(props) {
  const unit = props.unit;
  if (props.speed > props.maxSpeed) {
    return <div>Разрешенная скорость в населенном пункте в {UNIT[unit]} превышена!</div>;
  }
  return <div>Скорость в населенном пункте в {UNIT[unit]} не превышена.</div>;
}
 
function isValidSpeed(value){
  if(value !== null && value !== '' && value !== undefined){
    let intValue = parseInt(value);
    return !(isNaN(intValue) || !isFinite(intValue));
  }  
  return false
}
 
function convertToKph(mph) {
  return mph * 1.61;
}
 
function convertToMph(kph) {
  return kph / 1.61;
}
 
function сonvertSpeed(value, convertor) {  
  if(isValidSpeed(value)){
    const intValue = parseInt(value)
    let converted = convertor(intValue);
    let rounded = Math.round(converted * 100) / 100
    return rounded.toString()
  }  
  return '';
}
 
class SpeedSetter extends React.Component {
  constructor(props) {
    super(props);
    this.onChange = this.onChange.bind(this);
  }
 
  onChange(e) {
    this.props.onChangeSpeed(e.target.value);
  }
 
  render() {
    let speed = this.props.speed;
    let unit = this.props.unit;
    return (
      <p>
        <span>Введите скорость в "{UNIT[unit]}": </span>
        <input value={speed} onChange={this.onChange}/>
      </p>
    );
  }
}
 
class SpeedRadar extends React.Component {
  constructor(props){
    super(props);
    this.onChangeSpeedInKph = this.onChangeSpeedInKph.bind(this);
    this.onChangeSpeedInMph = this.onChangeSpeedInMph.bind(this);
    this.state = {speed: 0, unit: 'KPH'};
  }  
  
  onChangeSpeedInKph(speed) {
    this.setState({unit: 'KPH', speed});
    console.log(speed);
    console.log(this.state);
  }
  
  onChangeSpeedInMph(speed) {
    this.setState({unit: 'MPH', speed}); //??? Как он работает?
  }
  
  render() {
    console.log(this.state);
    const unit = this.state.unit;
    const speed = this.state.speed;
    const kph = unit === 'MPH' ? сonvertSpeed(speed, convertToKph) : speed;
    const mph = unit === 'KPH' ? сonvertSpeed(speed, convertToMph) : speed;
 
    return (
      <div>
        <SpeedSetter unit="KPH" speed={kph} onChangeSpeed={this.onChangeSpeedInKph}/>
        <SpeedSetter unit="MPH" speed={mph} onChangeSpeed={this.onChangeSpeedInMph}/> 
        <SpeedDetector speed={kph} unit="KPH" maxSpeed={MAX_SPEED_IN_CITY_IN_KPH}/>
      </div>
    );
  }
}
 
ReactDOM.render(<SpeedRadar />, document.getElementById('root'));
Пытаюсь разобраться как работает код, но туплю на строчке this.setState({unit: 'MPH', speed});.
Попытаюсь пошагово изложить, как я понимаю этот код.
1. Компонент SpeedRadar рендерит три элемента. Два SpeedSetter (забегая вперед - это будут input со span) и SpeedDetector (это будет div с текстом).
2. Следим за первым элементом. Т.е. за <SpeedSetter unit="KPH" speed={kph} onChangeSpeed={this.onChangeSpeedInKph}/>. Он передает в компонент SpeedSetter следующие props: {unit: "KPH", speed: {kph}, onChangeSpeed: {this.onChangeSpeedInKph}}.
3. Метод render() компонента Speedsetter возвращает <span>Введите скорость в "{UNIT[unit]}": </span> и <input value={speed} onChange={this.onChange}/>.
4.Оставим span в покое, так как там ничего не меняется и стало быть все просто. Следим дальше за input. У него два атрибута value={speed}(задает значение, что будет отображаться в input) и onChange={this.onChange}/>(обработчик события change).
5. В первый раз input рендерится со значением 0. Он возьмет это значение из переменной speed, которая в свою очередь берет его из this.props.speed ([I] let speed = this.props.speed;[I/]). В props.speed это speed={kph}. Смотрим, что находится в kph. Там вот такая запись: const kph = unit === 'MPH' ? сonvertSpeed(speed, convertToKph) : speed;. Стало быть при стартовом рендеринге первого input (с километрами в час) в kph попадет 0. Изначально первый input отобразиться с значением по умолчанию 0.
6. Когда мы в этом input сделаем изменения. Например, вставим туда копипастом 10, сработает атрибут onChange, который вызовет функцию onChange(e) {this.props.onChangeSpeed(e.target.value );}. Функция onChange вызовет через props функцию onChangeSpeedInKph(speed) {this.setState({unit: 'KPH', speed});} из SpeedRadar и передает ей аргументом 10.
7. И вот самое интересное (то, что мне непонятно). Каким-то образом setState из onChangeSpeedInKph затем переписывает this.state = {speed: 0, unit: 'KPH'} он становиться this.state = {speed: "10", unit: 'KPH'}. Но как это происходит? Мы же не написали this.setState({unit: 'KPH', this.state.speed = speed})? Мы написали this.setState({unit: 'KPH', speed}) Где speed это просто строка 10, как она смогла переписать this.state.speed? Похоже у меня критическое недопонимание как работает setState(). Объясните, пожалуйста.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.04.2021, 21:57
Ответы с готовыми решениями:

Асинхронность setState
this.state.error={text:'true',date:'false'} errorFunction = (prop) =&gt; { let arr = {...this.state.error}; arr = false; ...

Установить setState через функцию
Невозможно установить setState через функцию. В чем ошибка? export default class App extends Component { state = { text: ' ', ...

SetState не обновляет дочерние компоненты
Всего 2 компонента, родитель и ребёнок для вывода через map в строке 276. Саме дурацкое, что через консоль лог показывает, что общая цена...

8
Особый статус
 Аватар для FloppyDisc
623 / 221 / 164
Регистрация: 18.11.2015
Сообщений: 1,086
05.04.2021, 09:02
Тут дело не в стейте, вот пример:

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let state = {
    unit: 'MP', speed: 0, model: 'T', lol: 50,
};
 
const setState = (obj) => {
    state = {...state, ...obj};
}
 
const kek = 100;
const speed = 10;
const model = 'X';
 
setState({
    unit: 'KP', model, kek, speed, 
});
 
console.log(state);
1
38 / 14 / 4
Регистрация: 28.01.2020
Сообщений: 170
05.04.2021, 17:42  [ТС]
Да, но тут у вас синтаксис с операторами расширения
JavaScript
1
state = {...state, ...obj};
, а в моем случае
JavaScript
1
this.state = {speed: 0, unit: 'KPH'};
. Тут нет ...

Добавлено через 6 минут
Пока не щелкнуло

Добавлено через 16 минут
Если в вашем примере не использовать ..., т.е. написать, как у меня, то вернет объект с двумя вложенными объектами:

JavaScript
1
 state = { state, obj }; // { state: { unit: 'MP', speed: 0, model: 'T', lol: 50 },  obj: { unit: 'KP', model: 'X', kek: 100, speed: 10 } }
Добавлено через 2 часа 48 минут
Ладно бы так в setState у меня приходило:
JavaScript
1
    state = { unit: 'MP', speed: 10 };
Но приходить ведь так:
JavaScript
1
    state = { unit: 'MP', 10 };
или так, я точно не знаю:
JavaScript
1
    state = { unit: 'MP', "10" };
0
331 / 238 / 80
Регистрация: 15.11.2017
Сообщений: 453
Записей в блоге: 4
05.04.2021, 18:01
Лучший ответ Сообщение было отмечено Alborki как решение

Решение

Alborki, вы про shorthand property names?
https://developer.mozilla.org/... cript_2015

Или что-то другое непонятно?
1
38 / 14 / 4
Регистрация: 28.01.2020
Сообщений: 170
05.04.2021, 22:01  [ТС]
Непонятно почему это
JavaScript
1
this.setState({unit: 'MPH', speed});
меняет это
JavaScript
1
this.state = {speed: 0, unit: 'KPH'};
Как конкретно все происходит?
0
331 / 238 / 80
Регистрация: 15.11.2017
Сообщений: 453
Записей в блоге: 4
06.04.2021, 00:19
Ну так это недра реакта.

Когда мы вызываем this.setState() с передачей туда объекта, то говорим реакту обновить состояние.

Переданный в this.setState() объект не замещает старый объект, вместо этого реакт смотрит на свойства нового объекта и добавляет/меняет свйоства в "старом" объекте, а потом делает, если надо, очередной рендер компонента.
1
the hardway first
Эксперт JS
 Аватар для j2FunOnly
2475 / 1847 / 910
Регистрация: 05.06.2015
Сообщений: 3,610
06.04.2021, 09:33
Alborki, вам же сказали про shorthand property names
т. е.
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
const speed = 10;
 
const obj1 = {
  unit: 'FOO',
  speed: speed
}
 
// Объявления объектов obj1 и obj2 эквивалентны
 
const obj2 = {
  unit: 'FOO',
  speed // shorthand property names
}
1
38 / 14 / 4
Регистрация: 28.01.2020
Сообщений: 170
06.04.2021, 12:42  [ТС]
Ребят, всем спасибо!
Вроде понял.
Все полезно и про "недра Реакта" и про shorthand property names.

this.setState({unit: 'MPH', speed}); это тоже самое ,что и this.setState({unit: 'MPH', speed: 10});

А то, что работает без ..., это как-то React сам там у себя под капотом в "недрах" делает.
0
06.04.2021, 12:43

Не по теме:

Alborki, в компонентах React объединяет состояние, в Redux заменяет полностью, смотрите не запутайтесь ;)

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.04.2021, 12:43
Помогаю со студенческими работами здесь

Использование аргументов функции в setState
onAnswerClickHandler = index =&gt;{ if(index === 0){ this.setState({ answer: {0: 'good'} ...

Использование метода setState()
Здравствуйте. В оф. документации написано, что хранения информации, необходимой при каждом запросе использовать setState(). В class...

Не обновляется компонент при setState (JS React)
Есть массив в стейте, он копируется в masdop, после чего обновляется пушем, и юзается сетСтейт, почему не происходит отрисовка согласно...

Проблемы с setState при считывании данных с сервера
Здравствуйте, только начал изучать react, пытаюсь с базы загрузить информацию себе в приложение. Вроде бы делаю всё правильно, class App...

Как это работает? Я хочу спросить как работает C++ и где можно про него почитать
Привет, котоны. Заранее благодарю. Это будет моих общих вопросов нить, т.к. создавать целую ветку для каждого нецелесообразно. Я хочу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru