首页 > 解决方案 > 在 React 中,父组件如何从响应中设置状态并在子组件中执行异步获取功能?

问题描述

在我的反应应用程序中,我有一个子组件LoginForm,如下所示:

export class LoginForm extends React.Component {
    constructor(props) {
        super(props);
        this.login = this.login.bind(this);
    }

    async login() {
        let data = new FormData();
        data.append('User[email]', document.getElementById('app-login-form-email').value);
        data.append('User[password]', document.getElementById('app-login-form-password').value);
        let loginHandler = this.props.loginHandler;
        const req = await fetch('/site/login', {
            method: 'POST',
            body: data
        });
        const respJson = await req.json();
        loginHandler(respJson);
    }

    render() {
        return(
            <div id="app-login-form">
                <input type="text" id="app-login-form-email" value="test@app.com"></input>
                <br/>
                <input type="password" id="app-login-form-password" value="admin"></input>
                <br/>
                <button onClick={this.login}>Login</button>
            </div>
        );
    }
}

它有一个 prop loginHandler,它是一个从父组件传下来的函数,在这里可以看到完整的:

export class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            user: {
                isAuthenticated: props.isAuthenticated || false
            }
        }
        this.bodyHandlers = {
            handleUserLogin: this.handleUserLogin,
        };
        this.handleUserLogin = this.handleUserLogin.bind(this);
    }

    bodyHandlers;
    headerHandlers;
    footerHandlers;

    handleUserLogin(responseJson) {
        this.setState({
            user: {
                isAuthenticated: true,
                data: responseJson.user,
                jwt: responseJson.token
            }
        });
    }

    render() {
        return(
            <Router>
                <Header user={this.state.user} handlers={this.headerHandlers}/>
                <Body user={this.state.user} handlers={this.bodyHandlers}/>
                <Footer user={this.state.user} handlers={this.footerHandlers}/>
            </Router>
        );
    }
}

const domContainer = document.querySelector('#main');
ReactDOM.render(React.createElement(App), domContainer);

但是,每当我尝试此操作时,我都会在控制台中收到以下错误: Uncaught (in promise) TypeError: Cannot read property 'setState' of undefined

我有一个基本的理解,即在承诺范围内工作时,this处理起来会很棘手。我尝试了许多不同的排列,包括将函数的局部变量设置thatthis. 我也尝试过 fetch.then语法,这没什么区别。

我是否必须将获取代码实现为父组件中的函数并将其作为道具传递给子组件调用,还是我遗漏了什么?

谢谢。

标签: javascriptreactjsasync-awaitsetstate

解决方案


我认为问题在于您在绑定之前将该方法作为值分配给 bodyHandlers 对象。换个顺序试试:

constructor(props) {
    super(props);
    this.state = {
        user: {
            isAuthenticated: props.isAuthenticated || false
        }
    }

    this.handleUserLogin = this.handleUserLogin.bind(this);
    this.bodyHandlers = {
        handleUserLogin: this.handleUserLogin,
    };
}

推荐阅读