简体   繁体   中英

Why 'this' is undefined for child component, when click is passed from a parent component?

Trying to educate in React. It might be the case, that the whole structure is wrong however, this is it:

LoginComponent contains LoginForm, and passes onSubmit event down to the form. The submitForm triggers an actionCreator, that is why I have to use this.props.login . But when the call is happening this is undefined . I'm doing this, since LoginComponent will become an Auth component and contain the registration form as well. But is it correct in general?

import React from 'react';
import {connect} from "react-redux";
import {userActions} from "../../actions/auth.actions";
import LoginForm from "./loginForm";

class LoginComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            username: '',
            password: ''
        }
    }

    submitForm(username, password) {
        this.props.login(username, password);
    }

    render() {
        return (
            <>
                <LoginForm onSubmit={this.submitForm}/>
            </>
        );
    }
}

const mapStateProps = state => {
    const {isLoggedIn, isLoggingIn, user} = state;
    return {isLoggedIn, isLoggingIn, user};
};

const actionCreators = {
    login: userActions.login,
};

const connectedLoginComponent = connect(mapStateProps, actionCreators)(LoginComponent);
export {connectedLoginComponent as Login};

LoginForm:

import React, {useState} from 'react';
import PropTypes from 'prop-types';

const LoginForm = (props) => {
    const [username, setUsername] = useState('');
    const [password, setPassword] = useState('');
    const { onSubmit } = props;

    const handleSubmit = (e) => {
        e.preventDefault();
        onSubmit(username, password);
    };

    return (
        <>
            <form onSubmit={e => handleSubmit(e)}>
                <input
                    onChange={e => setUsername(e.target.value)}
                    value={username}
                    name={"username"}
                    type="text"
                    placeholder={'Username'}
                    required
                />
                <input
                    onChange={e => setPassword(e.target.value)}
                    value={password}
                    name={"password"}
                    type="text"
                    placeholder={'Password'}
                    required
                />
                <button>Login</button>
            </form>
        </>
    );
};

LoginForm.propTypes = {
    onSubmit: PropTypes.func,
};

export default LoginForm;

The function is not having this access we have to explicitly bind this to function or we can use arrow function.

Arrow function :

 submitForm = (username, password) => {
    this.props.login(username, password);
  }

Bind keep this in your constructor :

this.submitForm = this.submitForm.bind(this)
import React from 'react';
import {connect} from "react-redux";
import {userActions} from "../../actions/auth.actions";
import LoginForm from "./loginForm";

class LoginComponent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            username: '',
            password: ''
        }
    }

    submitForm =(username, password) => this.props.login(username, password);

    render() {
        return (
            <>
                <LoginForm onSubmit={this.submitForm}/>
            </>
        );
    }
}

const mapStateProps = state => {
    const {isLoggedIn, isLoggingIn, user} = state;
    return {isLoggedIn, isLoggingIn, user};
};

const actionCreators = {
    login: userActions.login,
};

const connectedLoginComponent = connect(mapStateProps, actionCreators)(LoginComponent);
export {connectedLoginComponent as Login};

and Login.jsx :

import React, {useState} from 'react';
import PropTypes from 'prop-types';

const LoginForm = ({onSubmit}) => {
    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");

    const handleSubmit = (e) => {
        e.preventDefault();
        onSubmit(username, password);
    };

    return (
        <>
            <form onSubmit={e => handleSubmit(e)}>
                <input
                    onChange={e => setUsername(e.target.value)}
                    value={username}
                    name={"username"}
                    type="text"
                    placeholder={'Username'}
                    required
                />
                <input
                    onChange={e => setPassword(e.target.value)}
                    value={password}
                    name={"password"}
                    type="text"
                    placeholder={'Password'}
                    required
                />
                <button>Login</button>
            </form>
        </>
    );
};

LoginForm.propTypes = {
    onSubmit: PropTypes.func,
};

export default LoginForm;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM