网站搜索

javascript - React 和 TS 范围/设置状态警告


我有一个相当简单的 React/Redux 应用(完整仓库)。我基本上有一个简单的网页表单,带有一对 onChange 处理程序。两者都抛出了相同的警告;

警告:setState(...): 只能更新已挂载或正在挂载的组件。这通常意味着你在一个已卸载的组件上调用了 setState()。

组件本身很简单——我已经在下面粘贴了代码。我使用了 TS 匿名()=>{} 语法来绕过 this 的作用域问题。

出于某种原因,当我在 componentDidMount 中记录 this 时,它显示为 _reactInternalInstance=ReactCompositeComponentWrapper。在 onChange 处理程序中记录的 this 没有该属性。

同样奇怪的是,componentDidMount 中 this 的 __proto__ 是 Login(如预期),但在回调处理函数中,它是 ReactComponent。

这两点都让我相信这实际上是一个作用域问题,但我无论如何都看不出我哪里出了错。有人以前见过这种情况吗?

import * as React from 'react';
import {connect} from 'react-redux';
import {FormControl, Button} from 'react-bootstrap';
import {IAppState} from '../store/IAppState';
import AuthActions from '../actions/AuthActions';

interface ILoginProps {
}
interface ILoginState {
    username: string;
    password: string;
}

export class Login extends React.Component<ILoginProps, ILoginState> {
    static propTypes = {};
    state = {
        username: '',
        password: ''
    };

    componentDidMount() {
        console.log('mounted');
        console.log(this);
    }

    usernameChange = (event: any): void => {
        console.log(this);
        this.setState({
            username: event.target.value,
            password: this.state.password
        });
    }

    passwordChange = (event: any): void => {
        this.setState({
            username: this.state.username,
            password: event.target.value
        });
    }

    login = (event: any): void => {
        event.preventDefault();
        console.log('login');
        console.log(this.state);
    }

    render() {
        return (
            <p>
                LOGIN
                <FormControl
                    type='text'
                    value={this.state.username}
                    placeholder='username'
                    onChange={this.usernameChange}
                />
                <FormControl
                    type='text'
                    value={this.state.password}
                    placeholder='password'
                    onChange={this.passwordChange}
                />
                <Button bsStyle='primary' onClick={this.login}>+</Button>
            </p>
        );
    }
}

export function mapStateToProps(state: IAppState) {
    return {};
}

export default connect(mapStateToProps, AuthActions)(Login);