【问题标题】:react apss props or state to child component将 apss 道具或状态反应到子组件
【发布时间】:2018-07-24 22:36:34
【问题描述】:

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

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 (LoginFormContainer.jsx:41) 处读取 null 的属性“电子邮件”

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

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

【问题讨论】:

    标签: javascript reactjs components state react-props


    【解决方案1】:

    在 react 组件中,this.state 只能引用该特定组件的内部状态。 React 不会自动传递状态——这就是 props 的用途。在这里,您可能无需将整个状态对象传递给 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 重命名为LoginFormContainerLoginFormContainer 重命名为Login

    如果不清楚,请进一步阅读道具:https://reactjs.org/docs/components-and-props.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-16
      • 2018-01-13
      • 1970-01-01
      • 2018-07-10
      • 2018-03-08
      • 2019-11-26
      • 2020-10-08
      • 1970-01-01
      相关资源
      最近更新 更多