В компоненте хочу реализовать таймер, по истечении которого надо сделать запрос. Пошуршал по гугглу и стеку примеры таймеров, прикрутил свое. Получилось следующее:
export default class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
secondsRemaining: 0
}
}
componentDidUpdate(prevProps, prevState) {
let {secondsRemaining} = prevState;
if (secondsRemaining === 0) {
// REQUEST
} else {
this.interval = setInterval(this.tick, 1000);
}
}
handleItemClick = () => {
this.setState({
activeItem: itemIndex,
secondsRemaining : data.time && data.time
});
};
tick = () => {
this.setState({secondsRemaining: this.state.secondsRemaining - 1});
if (this.state.secondsRemaining <= 0) {
clearInterval(this.interval);
}
};
}
По клику на айтем меню задействуется хендлер handleItemClick, который сетит в стейт secondsRemaining в секундах(например 60 секунд). Далее срабатывает didUpdate и условие таково, что когда secondsRemaining будет равно нулю, то надо выполнить запрос, если нет, ты с интервалом в 1 секунду методом SetInterval мы отсчитываем время. Это работает,но не совсем так как надо. Он доходит до 0 и продолжает отнимать -1,-2,-3 и так о бесконечности. Какой-то косяк в моей логике,но я не пойму какой. Подскажите пожалуйста
componentDidUpdate(prevProps, prevState) {
let {secondsRemaining} = prevState;
if (secondsRemaining === 0) {
// REQUEST
} else {
this.interval = setInterval(this.tick, 1000);
}
}
Метод componentDidUpdate вызывается каждый раз, как у вас срабатывает апдейт компонента, даже когда вы уже запустили таймер, то есть после каждого вызова таймера, вызывается этот метод, где проверяется условие, которое снова срабатывает ( таймер обновляется, правда старый таймер никуда не исчезает )
Поэтому в итоге у вас куча таймеров в памяти = утечка памяти
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
secondsRemaining: 100
};
}
componentDidUpdate(prevProps, prevState) {
let { secondsRemaining } = prevState;
if (secondsRemaining === 0) {
// REQUEST
} else if (!this.interval) { // только если еще нет таймера
this.interval = setInterval(this.tick, 10);
}
}
componentWillUnmount() {
// обязательно при анмаунте удаляем таймер
clearInterval(this.interval);
this.interval = undefined;
}
handleItemClick = () => {
this.setState({
secondsRemaining: 100
});
};
tick = () => {
this.setState({ secondsRemaining: this.state.secondsRemaining - 1 });
if (this.state.secondsRemaining <= 0) {
clearInterval(this.interval);
this.interval = undefined;
}
};
render() {
return (
<div>
<div>{this.state.secondsRemaining}</div>
<button onClick={this.handleItemClick}>click</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<MyComponent />, rootElement);
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости