setState() или свойства класса в React?
Здравствуй, путник. Я новичок в реакте, и читая документацию увидел, что setState() обновляет весь компонент разом, после чего на практике выявил следующее:
Предположим, есть условный реактовский компонент в двух реализациях. Во второй реализации отсутствует state (вернее, он есть, но пустой), и вместо него используется поле класса. В обоих случаях состояние компонента обновляется, и число в блоке div повышается при нажатии на него. Второй вариант выглядит чище и требует меньше затрат времени на написание, плюс удобнее в ориентировании, но есть ведь же загвоздка, да?
Должны ли быть различия в производительности?
Как это отразится на тестируемости?
Есть ли какие-либо специфические моменты, до которых я пока в изучении даже не дошел?
Вариант 1
interface IState {
counter: number;
}
export class ExampleComponent extends React.Component<any, IState> {
//конструктор опустим
private increaseCounter(e: React.MouseEvent) {
this.state = {
counter: this.state.counter + 1
};
}
public render() {
<div onClick={this.increaseCounter}>
{this.state.counter}
</div>
}
}
Вариант 2
export class ExampleComponent extends React.Component<any, {}> {
private counter: number = 0;
private increaseCounter(e: React.MouseEvent) {
this.counter++;
this.setState({});
}
public render() {
<div onClick={this.increaseCounter}>
{this.counter}
</div>
}
}
Ответы (1 шт):
Изменение свойства инстанса класса не вызывает перерисовку компонента самостоятельно. В качестве кейса использования, могу разве что предложить положить туда Subscription из библиотеки RxJS
Смысл React - создать единый стандарт написания кода фронтенд приложения, а не повысить производительность. Поэтому, для обновление счетчика
counterиспользуйте именноsetState({ counter: this.state.counter + 1 }), иначе выглядит весьма вульгарно
import React from 'react';
import { interval } from 'rxjs';
export class TestComponent extends React.Component {
subscription = null;
constructor(props) {
super(props);
this.state = {
counter: 0,
};
};
componentDidMount = () => {
this.subscription = interval(1_000).subscribe(() => {
this.setState({ counter: this.state.counter + 1 })
});
};
componentWillUnmount = () => {
this.subscription.unsubscribe();
};
public render = () => {
<div>
{this.counter}
</div>
};
}
P.S. На самом деле, удобнее именно держать всё состояние внутри объекта state в сгруппированном виде, даже если бы можно было использовать свойства класса, проблематично было бы понять, что используется в render, а что нет)