TypeScript + React: Avoid setState on unmounted components
I know that a common pattern of avoiding calling .setState()
on an unmounted component is by adding a private property such as _isMounted
to keep track of it, as mentioned in a blog.
I've been using this method like this:
class Hello extends React.PureComponent{
_isMounted = false;
constructor(props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
// ...
}
Everything was fine until I started to use TypeScript. I tried to do this in the same way:
class Hello extends React.PureComponent<Props, State> {
private _isMounted: boolean;
constructor(props: Props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
}
But then it always throws a type error:
TypeError: Cannot set property _isMounted of #<Component> which has only a getter
For now, the only solution I know is to explicitly write a setter for it. But I don't really understand if this is the expected way to do it. Doesn't TypeScript generate getter and setter automatically?
Updated:
A codesandbox example: https://codesandbox.io/s/l59wnqy5zz
reactjs typescript
|
show 1 more comment
I know that a common pattern of avoiding calling .setState()
on an unmounted component is by adding a private property such as _isMounted
to keep track of it, as mentioned in a blog.
I've been using this method like this:
class Hello extends React.PureComponent{
_isMounted = false;
constructor(props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
// ...
}
Everything was fine until I started to use TypeScript. I tried to do this in the same way:
class Hello extends React.PureComponent<Props, State> {
private _isMounted: boolean;
constructor(props: Props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
}
But then it always throws a type error:
TypeError: Cannot set property _isMounted of #<Component> which has only a getter
For now, the only solution I know is to explicitly write a setter for it. But I don't really understand if this is the expected way to do it. Doesn't TypeScript generate getter and setter automatically?
Updated:
A codesandbox example: https://codesandbox.io/s/l59wnqy5zz
reactjs typescript
I think the problem must be in code you haven't shown. In theHello
class shown,_isMounted
is clearly a data property, not an accessor property.
– T.J. Crowder
Nov 21 '18 at 14:57
The playground is happy with it (removed the React-isms, which shouldn't matter).
– T.J. Crowder
Nov 21 '18 at 14:58
I think _isMounted is a private property of React.Component. Rename it and it should work.
– Stramski
Nov 21 '18 at 15:13
1
or better yet, teardown any async stuff when unmount happens. eg if you havesetTimeout
/Interval
, keep a reference and callclearTimeout
. reactjs.org/blog/2015/12/16/ismounted-antipattern.html
– Dimitar Christoff
Nov 21 '18 at 15:17
@Stramski Yes it did work when I change the name! Thanks! But why didn't the private property we define here overwrite the one from React.Component?
– catlicechew
Nov 21 '18 at 15:24
|
show 1 more comment
I know that a common pattern of avoiding calling .setState()
on an unmounted component is by adding a private property such as _isMounted
to keep track of it, as mentioned in a blog.
I've been using this method like this:
class Hello extends React.PureComponent{
_isMounted = false;
constructor(props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
// ...
}
Everything was fine until I started to use TypeScript. I tried to do this in the same way:
class Hello extends React.PureComponent<Props, State> {
private _isMounted: boolean;
constructor(props: Props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
}
But then it always throws a type error:
TypeError: Cannot set property _isMounted of #<Component> which has only a getter
For now, the only solution I know is to explicitly write a setter for it. But I don't really understand if this is the expected way to do it. Doesn't TypeScript generate getter and setter automatically?
Updated:
A codesandbox example: https://codesandbox.io/s/l59wnqy5zz
reactjs typescript
I know that a common pattern of avoiding calling .setState()
on an unmounted component is by adding a private property such as _isMounted
to keep track of it, as mentioned in a blog.
I've been using this method like this:
class Hello extends React.PureComponent{
_isMounted = false;
constructor(props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
// ...
}
Everything was fine until I started to use TypeScript. I tried to do this in the same way:
class Hello extends React.PureComponent<Props, State> {
private _isMounted: boolean;
constructor(props: Props) {
super(props);
this.state = {
// ...
};
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
}
But then it always throws a type error:
TypeError: Cannot set property _isMounted of #<Component> which has only a getter
For now, the only solution I know is to explicitly write a setter for it. But I don't really understand if this is the expected way to do it. Doesn't TypeScript generate getter and setter automatically?
Updated:
A codesandbox example: https://codesandbox.io/s/l59wnqy5zz
reactjs typescript
reactjs typescript
edited Nov 21 '18 at 15:25
catlicechew
asked Nov 21 '18 at 14:53
catlicechewcatlicechew
415
415
I think the problem must be in code you haven't shown. In theHello
class shown,_isMounted
is clearly a data property, not an accessor property.
– T.J. Crowder
Nov 21 '18 at 14:57
The playground is happy with it (removed the React-isms, which shouldn't matter).
– T.J. Crowder
Nov 21 '18 at 14:58
I think _isMounted is a private property of React.Component. Rename it and it should work.
– Stramski
Nov 21 '18 at 15:13
1
or better yet, teardown any async stuff when unmount happens. eg if you havesetTimeout
/Interval
, keep a reference and callclearTimeout
. reactjs.org/blog/2015/12/16/ismounted-antipattern.html
– Dimitar Christoff
Nov 21 '18 at 15:17
@Stramski Yes it did work when I change the name! Thanks! But why didn't the private property we define here overwrite the one from React.Component?
– catlicechew
Nov 21 '18 at 15:24
|
show 1 more comment
I think the problem must be in code you haven't shown. In theHello
class shown,_isMounted
is clearly a data property, not an accessor property.
– T.J. Crowder
Nov 21 '18 at 14:57
The playground is happy with it (removed the React-isms, which shouldn't matter).
– T.J. Crowder
Nov 21 '18 at 14:58
I think _isMounted is a private property of React.Component. Rename it and it should work.
– Stramski
Nov 21 '18 at 15:13
1
or better yet, teardown any async stuff when unmount happens. eg if you havesetTimeout
/Interval
, keep a reference and callclearTimeout
. reactjs.org/blog/2015/12/16/ismounted-antipattern.html
– Dimitar Christoff
Nov 21 '18 at 15:17
@Stramski Yes it did work when I change the name! Thanks! But why didn't the private property we define here overwrite the one from React.Component?
– catlicechew
Nov 21 '18 at 15:24
I think the problem must be in code you haven't shown. In the
Hello
class shown, _isMounted
is clearly a data property, not an accessor property.– T.J. Crowder
Nov 21 '18 at 14:57
I think the problem must be in code you haven't shown. In the
Hello
class shown, _isMounted
is clearly a data property, not an accessor property.– T.J. Crowder
Nov 21 '18 at 14:57
The playground is happy with it (removed the React-isms, which shouldn't matter).
– T.J. Crowder
Nov 21 '18 at 14:58
The playground is happy with it (removed the React-isms, which shouldn't matter).
– T.J. Crowder
Nov 21 '18 at 14:58
I think _isMounted is a private property of React.Component. Rename it and it should work.
– Stramski
Nov 21 '18 at 15:13
I think _isMounted is a private property of React.Component. Rename it and it should work.
– Stramski
Nov 21 '18 at 15:13
1
1
or better yet, teardown any async stuff when unmount happens. eg if you have
setTimeout
/ Interval
, keep a reference and call clearTimeout
. reactjs.org/blog/2015/12/16/ismounted-antipattern.html– Dimitar Christoff
Nov 21 '18 at 15:17
or better yet, teardown any async stuff when unmount happens. eg if you have
setTimeout
/ Interval
, keep a reference and call clearTimeout
. reactjs.org/blog/2015/12/16/ismounted-antipattern.html– Dimitar Christoff
Nov 21 '18 at 15:17
@Stramski Yes it did work when I change the name! Thanks! But why didn't the private property we define here overwrite the one from React.Component?
– catlicechew
Nov 21 '18 at 15:24
@Stramski Yes it did work when I change the name! Thanks! But why didn't the private property we define here overwrite the one from React.Component?
– catlicechew
Nov 21 '18 at 15:24
|
show 1 more comment
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53414723%2ftypescript-react-avoid-setstate-on-unmounted-components%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53414723%2ftypescript-react-avoid-setstate-on-unmounted-components%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I think the problem must be in code you haven't shown. In the
Hello
class shown,_isMounted
is clearly a data property, not an accessor property.– T.J. Crowder
Nov 21 '18 at 14:57
The playground is happy with it (removed the React-isms, which shouldn't matter).
– T.J. Crowder
Nov 21 '18 at 14:58
I think _isMounted is a private property of React.Component. Rename it and it should work.
– Stramski
Nov 21 '18 at 15:13
1
or better yet, teardown any async stuff when unmount happens. eg if you have
setTimeout
/Interval
, keep a reference and callclearTimeout
. reactjs.org/blog/2015/12/16/ismounted-antipattern.html– Dimitar Christoff
Nov 21 '18 at 15:17
@Stramski Yes it did work when I change the name! Thanks! But why didn't the private property we define here overwrite the one from React.Component?
– catlicechew
Nov 21 '18 at 15:24