Во многих моих компонентах мне нужно сделать что-то вроде этого:
handleSubmit() {
this.setState({loading: true})
someAsyncFunc()
.then(() => {
return this.props.onSuccess()
})
.finally(() => this.setState({loading: false}))
}
Функция onSuccess
- может быть или не быть обещанием (если оно
loading
должен оставаться верным до тех пор, пока не будет решен) - может отключить или не отключить компонент (он может закрыть модальный режим, в котором находится этот компонент, или даже перейти на другую страницу)
Если функция отключает компонент, this.setState({loading: false})
явно вызывает предупреждение Can't call setState (or forceUpdate) on an unmounted component.
Мои 2 вопроса:
- Существует ли простой способ избежать этой проблемы?Я не хочу устанавливать переменные
_isMounted
в componentDidMount
и componentWillUnmount
, а затем проверять их при необходимости в большинстве моих компонентов, плюс я могу забыть сделать это в следующий раз, написав что-то вроде этого ... - Это действительно проблема?Я знаю, что, согласно предупреждению,
it indicates a memory leak in my application
, но это не утечка памяти в этом случае, не так ли?Может быть, игнорирование предупреждения будет в порядке ...
РЕДАКТИРОВАТЬ: Второй вопрос немного важнее для меня, чем первый.Если это действительно проблема, и я просто не могу вызвать setState
для неустановленного компонента, я, вероятно, сам найду обходной путь.Но мне любопытно, если я не могу просто проигнорировать это.
Живой пример проблемы:
const someAsyncFunc = () => new Promise(resolve => {
setTimeout(() => {
console.log("someAsyncFunc resolving");
resolve("done");
}, 2000);
});
class Example extends React.Component {
constructor(...args) {
super(...args);
this.state = {loading: false};
}
componentDidMount() {
setTimeout(() => this.handleSubmit(), 100);
}
handleSubmit() {
this.setState({loading: true})
someAsyncFunc()
/*
.then(() => {
return this.props.onSuccess()
})
*/
.finally(() => this.setState({loading: false}))
}
render() {
return <div>{String(this.state.loading)}</div>;
}
}
class Wrapper extends React.Component {
constructor(props, ...rest) {
super(props, ...rest);
this.state = {
children: props.children
};
}
componentDidMount() {
setTimeout(() => {
console.log("removing");
this.setState({children: []});
}, 1500)
}
render() {
return <div>{this.state.children}</div>;
}
}
ReactDOM.render(
<Wrapper>
<Example />
</Wrapper>,
document.getElementById("root")
);
.as-console-wrapper {
max-height: 100% !important;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>