反应apss道具或状态到子组件

时间:2018-02-14 11:10:49

标签: javascript reactjs components state react-props

我需要一些关于反应组件的帮助。我是这方面的新手,我正在制作一个带有反应的网络应用程序,我想分离表单和容器,我做了一些但没有工作。

  

LoginFormContainer.jsx

import React from "react";
import {
    Row,
    Col,
    Card,
    CardTitle,
    Form,
    FormGroup,
    Button,
    Label,
    Input,
    FormText
} from "reactstrap";

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

    render() {
        return (
            <Row>
                <Col
                    md={{ size: 8, offset: 2 }}
                    sm={{ size: 8, offset: 2 }}
                    lg={{ size: 6, offset: 3 }}
                >
                    <Card body className="auth-card">
                        <CardTitle className="text-center mb-4">
                            Giriş Yap
                        </CardTitle>
                        <Form onSubmit={this.handleSubmit}>
                            <FormGroup row>
                                <Label sm="2" className="form-control-label">
                                    Email
                                </Label>
                                <Col sm="10">
                                    <Input
                                        type="email"
                                        name="email"
                                        value={this.state.email}
                                        onChange={event =>
                                            this.handleUserInput(event)
                                        }
                                        className={`${this.errorClass(
                                            "email"
                                        )}`}
                                    />
                                    {this.state.formErrors.email ? (
                                        <div className="invalid-feedback">
                                            {this.state.formErrors.email}
                                        </div>
                                    ) : (
                                        ""
                                    )}
                                </Col>
                            </FormGroup>
                            <FormGroup row>
                                <Label sm="2" className="form-control-label">
                                    Şifre
                                </Label>
                                <Col sm="10">
                                    <Input
                                        type="password"
                                        name="password"
                                        value={this.state.password}
                                        onChange={event =>
                                            this.handleUserInput(event)
                                        }
                                        className={`${this.errorClass(
                                            "password"
                                        )}`}
                                    />
                                    {this.state.formErrors.password ? (
                                        <div className="invalid-feedback">
                                            {this.state.formErrors.password}
                                        </div>
                                    ) : (
                                        ""
                                    )}
                                </Col>
                            </FormGroup>
                            <Button
                                color="primary"
                                className="float-right"
                                type="submit"
                                disabled={!this.state.formValid}
                            >
                                {this.state.button[this.state.formSubmit]}
                            </Button>
                        </Form>
                    </Card>
                </Col>
            </Row>
        );
    }
}

export default LoginFormContainer;
  

LoginForm.jsx

import React from "react"
import LoginFormContainer from './LoginFormContainer'

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

        this.handleUserInput = this.handleUserInput.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);

        this.state = {
            email: "",
            password: "",
            formErrors: { email: "", password: "" },
            emailValid: false,
            passwordValid: false,
            formValid: false,
            formSubmit : 'normal',
            button: {
                normal: "Giriş Yap",
                loading: <i className="fa fa-fw fa-spin fa-spinner"></i>
            }
        };
    }

    handleSubmit(e) {
        this.setState({
            formSubmit: 'loading'
        });

        e.preventDefault();
    }

    handleUserInput(e) {
        const name = e.target.name;
        const value = e.target.value;
        this.setState({ [name]: value }, () => {
            this.validateField(name, value);
        });
    }

    validateField(fieldName, value) {
        let fieldValidationErrors = this.state.formErrors;
        let emailValid = this.state.emailValid;
        let passwordValid = this.state.passwordValid;

        switch (fieldName) {
            case "email":
                emailValid = value.match(
                    /^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i
                );
                fieldValidationErrors.email = emailValid ? "" : " is invalid";
                break;
            case "password":
                passwordValid = value.length >= 6;
                fieldValidationErrors.password = passwordValid
                    ? ""
                    : " is too short";
                break;
            default:
                break;
        }
        this.setState(
            {
                formErrors: fieldValidationErrors,
                emailValid: emailValid,
                passwordValid: passwordValid
            },
            this.validateForm
        );
    }

    validateForm() {
        this.setState({
            formValid: this.state.emailValid && this.state.passwordValid
        });
    }

    errorClass(key) {
        return this.state[key].length > 0 &&
            this.state.formErrors[key].length > 0
            ? "is-invalid"
            : "";
    }

    render() {
        return <LoginFormContainer />;
    }
}

export default Login;

代码会出现此错误:

  

TypeError:无法在t.value读取null的属性'email'(LoginFormContainer.jsx:41)

     

line41是:value = {this.state.email}

问题出在哪里?如何将道具或州(或两者)传递给子组件?

1 个答案:

答案 0 :(得分:0)

在反应组件中,this.state只能引用该特定组件的内部状态。 React并没有自动传递状态 - 这就是道具的用途。在这里,您可以将整个状态对象传递给LoginFormContainer组件。

class Login extends React.Component {
  // ...

  render() {
    return <LoginFormContainer formState={this.state} />
  }
}

class LoginFormContainer {
  render() {
    // instead of this.state.email, access this.props.formState.email
    // so your input would look like this:
    <Input
      type="email"
      name="email"
      value={this.props.formState.email}
      // other props...
    />
  }
}

另外,另一个不相关的提示:通常容器组件是关注状态的组件。在这里看起来你已经倒退了,所以我建议将Login重命名为LoginFormContainer,将LoginFormContainer重命名为Login

如果有任何不明确的话,请继续阅读道具:https://reactjs.org/docs/components-and-props.html