React:如何从另一个具有状态变量的组件运行函数

时间:2018-09-19 15:11:36

标签: javascript reactjs

我有这个免费组件:

我的LoginForm:

import React, { Component } from "react";
import { Pane, TextInputField, Checkbox, Button } from "evergreen-ui";
import { validateEmail, validatePassword } from "./FormValidator";

class LoginForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      passwordErr: {
        status: false,
        value: ""
      },
      emailErr: {
        status: false,
        value: ""
      },
      email: "",
      password: "",
      CheckBoxchecked: false
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleCheckbox = this.handleCheckbox.bind(this);
  }

  handleEmailInput = e => {
    const email = e.target.value;
    this.setState({ email: email });
  };

  handlePasswordInput = e => {
    const password = e.target.value;
    this.setState({ password: password });
  };

  handleCheckbox() {
    this.setState({
      CheckBoxchecked: !this.state.CheckBoxchecked
    });
  }

  handleSubmit() {
    if (this.checkFormStatus()) {
      alert("Form OK");
    }
  }

  checkFormStatus() {
    // form validation middleware
    const { email, password } = this.state;
    const emailErr = validateEmail(email);
    const passwordErr = validatePassword(password);

    if (!emailErr.status && !passwordErr.status) {
      return true;
    } else {
      this.setState({
        emailErr,
        passwordErr
      });
      return false;
    }
  }

  render() {
    return (
      <Pane padding={15}>
        <TextInputField
          tabIndex={0}
          required
          isInvalid={this.state.emailErr.status}
          validationMessage={
            this.state.emailErr.status ? this.state.emailErr.value : false
          }
          onChange={this.handleEmailInput}
          value={this.state.email}
          appearance="neutral"
          type="email"
          label="Your email-address"
          inputHeight={36}
          //description="We’ll need your email-address to create an new account"
        />
        <TextInputField
          required
          validationMessage={
            this.state.passwordErr.status ? this.state.passwordErr.value : false
          }
          isInvalid={this.state.passwordErr.status}
          onChange={this.handlePasswordInput}
          value={this.state.password}
          appearance="neutral"
          label="Your Password"
          type="password"
          inputHeight={36}
          //description="Create a secure password to protect your account"
        />
        <Checkbox
          label="Keep me logged in"
          checked={this.state.CheckBoxchecked}
          onChange={this.handleCheckbox}
        />
      </Pane>
    );
  }
}
export default LoginForm;

我的导出LoginFormButton:

export class LoginFormButton extends Component {

  render() {
    return (
      <Button
        appearance="primary"
        marginLeft={8}
        marginRight={16}
        intent="success"
        onClick={} //How can i call handleSubmit() from here?
      >
        Login
      </Button>
    );
  }
}

和我的对话框...

import ReactDOM from "react-dom";
import LoginForm from './LoginForm';
import LoginFormButton from './LoginFormButton';

class LoginDialog extends Components {

  render(
    return(
      <Dialog>
        <LoginForm/>
        <div className="Footer">
          <LoginFormButton/>
        </div>
      </Dialog>   
    );  
  )
}

我将函数handleSubmit()存储在LoginForm组件中。我想从LoginFormButton调用这些函数。此按钮包含在对话框组件中:

enter image description here

我该怎么做?感谢您的回答和我们的帮助。我是一个初学者,所以我不知道该如何实现。

3 个答案:

答案 0 :(得分:1)

看起来,您想要一个LoginForm组件和一个LoginFormButton来处理表单提交。

import React, { Component } from "react";
import { Pane, TextInputField, Checkbox, Button } from "evergreen-ui";
import { validateEmail, validatePassword } from "./FormValidator";

const LoginFormButton = ({ handleSubmit }) => {
    return (
      <Button
        appearance="primary"
        marginLeft={8}
        marginRight={16}
        intent="success"
        onClick={() => handleSubmit()} // or just -> onClick={handleSubmit}
      >
        Login
      </Button>
    );
}

class LoginForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      passwordErr: {
        status: false,
        value: ""
      },
      emailErr: {
        status: false,
        value: ""
      },
      email: "",
      password: "",
      CheckBoxchecked: false
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleCheckbox = this.handleCheckbox.bind(this);
  }

  handleEmailInput = e => {
    const email = e.target.value;
    this.setState({ email: email });
  };

  handlePasswordInput = e => {
    const password = e.target.value;
    this.setState({ password: password });
  };

  handleCheckbox() {
    this.setState({
      CheckBoxchecked: !this.state.CheckBoxchecked
    });
  }

  handleSubmit() {
    if (this.checkFormStatus()) {
      alert("Form OK");
    }
  }

  checkFormStatus() {
    // form validation middleware
    const { email, password } = this.state;
    const emailErr = validateEmail(email);
    const passwordErr = validatePassword(password);

    if (!emailErr.status && !passwordErr.status) {
      return true;
    } else {
      this.setState({
        emailErr,
        passwordErr
      });
      return false;
    }
  }

  render() {
    return (
      <Pane padding={15}>
        <TextInputField
          tabIndex={0}
          required
          isInvalid={this.state.emailErr.status}
          validationMessage={
            this.state.emailErr.status ? this.state.emailErr.value : false
          }
          onChange={this.handleEmailInput}
          value={this.state.email}
          appearance="neutral"
          type="email"
          label="Your email-address"
          inputHeight={36}
          //description="We’ll need your email-address to create an new account"
        />
        <TextInputField
          required
          validationMessage={
            this.state.passwordErr.status ? this.state.passwordErr.value : false
          }
          isInvalid={this.state.passwordErr.status}
          onChange={this.handlePasswordInput}
          value={this.state.password}
          appearance="neutral"
          label="Your Password"
          type="password"
          inputHeight={36}
          //description="Create a secure password to protect your account"
        />
        <Checkbox
          label="Keep me logged in"
          checked={this.state.CheckBoxchecked}
          onChange={this.handleCheckbox}
        />
        <LoginFormButton
          handleSubmit={this.handleSubmit}
        />
      </Pane>
    );
  }
}
export default LoginForm;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

1)验证将在LoginForm组件中进行,除非您将this.state.passwordthis.state.email传递给LoginFormButton组件。我不建议这样做,因为可以在LoginForm组件中处理验证。

2)HandleSubmit函数可以作为来自LoginFormButton组件的props传递给LoginForm组件,并且可以在该组件内直接使用。

我建议您在状态变量中遵循JS标准来命名约定(camelCases)。并使用箭头函数,这样就不必显式绑定函数,除非另有说明。

我将您LoginFormButton更改为无状态组件,因为它不需要状态。这样更好,这也是React社区鼓励的。

答案 1 :(得分:0)

检查以下更正的代码

LoginForm组件

import React, { Component } from "react";
import { Pane, TextInputField, Checkbox, Button } from "evergreen-ui";
import { validateEmail, validatePassword } from "./FormValidator";

class LoginForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      passwordErr: {
        status: false,
        value: ""
      },
      emailErr: {
        status: false,
        value: ""
      },
      email: "",
      password: "",
      CheckBoxchecked: false
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleCheckbox = this.handleCheckbox.bind(this);
  }

  handleEmailInput = e => {
    const email = e.target.value;
    this.setState({ email: email });
  };

  handlePasswordInput = e => {
    const password = e.target.value;
    this.setState({ password: password });
  };

  handleCheckbox() {
    this.setState({
      CheckBoxchecked: !this.state.CheckBoxchecked
    });
  }

  handleSubmit() {
    if (this.checkFormStatus()) {
      alert("Form OK");
    }
  }

  checkFormStatus() {
    // form validation middleware
    const { email, password } = this.state;
    const emailErr = validateEmail(email);
    const passwordErr = validatePassword(password);

    if (!emailErr.status && !passwordErr.status) {
      return true;
    } else {
      this.setState({
        emailErr,
        passwordErr
      });
      return false;
    }
  }

  render() {
    return (
      <Pane padding={15}>
        <TextInputField
          tabIndex={0}
          required
          isInvalid={this.state.emailErr.status}
          validationMessage={
            this.state.emailErr.status ? this.state.emailErr.value : false
          }
          onChange={this.handleEmailInput}
          value={this.state.email}
          appearance="neutral"
          type="email"
          label="Your email-address"
          inputHeight={36}
          //description="We’ll need your email-address to create an new account"
        />
        <TextInputField
          required
          validationMessage={
            this.state.passwordErr.status ? this.state.passwordErr.value : false
          }
          isInvalid={this.state.passwordErr.status}
          onChange={this.handlePasswordInput}
          value={this.state.password}
          appearance="neutral"
          label="Your Password"
          type="password"
          inputHeight={36}
          //description="Create a secure password to protect your account"
        />
        <Checkbox
          label="Keep me logged in"
          checked={this.state.CheckBoxchecked}
          onChange={this.handleCheckbox}
        />
        <div className="Footer">
          <LoginFormButton handleSubmit={this.handleSubmit} />
        </div>
      </Pane>
    );
  }
}
export default LoginForm;

LoginFormButton组件

export class LoginFormButton extends Component {
  constructor(props) {
    super(props);
    this.state = {

    };
  }

  render() {
    return (
      <div>
        <Button
          appearance="primary"
          marginLeft={8}
          marginRight={16}
          intent="success"
          onClick={this.props.handleSubmit}
        >
          Login
        </Button>
      </div>
    );
  }
}

对话框组件

import ReactDOM from "react-dom";
import LoginForm from './LoginForm';
import LoginFormButton from './LoginFormButton';

class LoginDialog extends Components {

  render(
    return(
      <Dialog>
        <LoginForm/>
      </Dialog>   
    );  
  )
}

答案 2 :(得分:0)

我建议您不要将业务逻辑放在按钮组件中。该按钮的唯一工作应该是通知使用它的人该按钮已被单击。通过向按钮传递道具来完成:

export class LoginFormButton extends Component {
  render() {
    return (
      <Button
        appearance="primary"
        marginLeft={8}
        marginRight={16}
        intent="success"
        onClick={this.props.onClick}
      >
        Login
      </Button>
    );
  }
}

然后,无论使用什么组件的道具都将是发生业务逻辑的地方。其他解决方案假定登录表单按钮将是登录表单的一部分,这可能也是我的做法。所以我的建议是将这部分从LoginDialog中删除:

<div className="Footer">
  <LoginFormButton/>
</div>

将其移至LoginForm.js,并添加回调:

render() {
  return (
    <Pane padding={15}>
      {/* inputs and checkbox components omitted */}
      <div className="Footer" onClick={this.handleSubmit}>
        <LoginFormButton/>
      </div>
    </Pane>
  )
}

如果由于某种原因您不能将按钮移到表单中,那么您将有更多工作要做。您需要将业务逻辑上移到组件,该组件是按钮和文本输入的共享祖先,即LoginDialog。因此,您将采用LoginForm中当前包含的大多数代码,并将其移至LoginDialog。这包括将状态从LoginForm上移到LoginDialog。然后,LoginForm将需要回调以将相关更改传递回loginDialog,以便对话框可以更新其状态。当按下按钮时,该事件将进入LoginDialog中的handleSubmit。

这种将状态上移到父级的行为在React开发中非常普遍,足以在React的教程页面https://reactjs.org/tutorial/tutorial.html#lifting-state-up中提到。因此,这是解决问题的有效方法,但是在这种情况下,我认为您最好将按钮移至表单中