ReactJS从子组件更改状态

时间:2019-08-08 13:11:55

标签: reactjs state

在研究ReactJS时,我遇到了一个难题。我有一个子组件,其中包含一个TextField组件和一个Button组件:

class LoginForm extends Component {
  constructor(props,context){
    super(props,context)
    this.loginUser = this.loginUser.bind(this);
  }
  loginUser(){
    this.setState({
      errorflage: true,
      errormsg: "This is a required Field"
    })
  }
  render(){
    return(
      <Panel width="375" height="0" halign="center" valign="center">
        <h3>Please Sign In</h3>
        <TextField type="text" label="Email Address:" id="emailaddress" name="emailaddress" focus/>
        <TextField type="password" label="Password:" id="password" name="password"/>
        <LoginButton size="small" proc={this.loginUser}/>
      </Panel>
    )
  }
}
export default LoginForm

TextField组件:

export const TextField = class TextField extends Component {
  constructor(props){
    super(props);
    this.state = {
      errorflag: false,
      errormsg: ""
    }
    this.myRef = React.createRef();
  }
  componentDidMount(){
    if(this.props.focus){
      this.myRef.current.focus();
    }
  }
  render(){
    var errid = this.props.id + "_errmsg";
    var labelStyle = "w3-label-font";
    var inputStyle = "w3-input w3-border w3-light-grey w3-round";
    return(
      <div>
        <label className={labelStyle}><b>{this.props.label}</b></label>
        <input className={inputStyle} type={this.props.type} id={this.props.id} name={this.props.name} ref={this.myRef}/>
        <div id={errid} className="error-msg">{this.state.errormsg}</div>
      </div>
    );
  };
}

按钮组件:

export const Button = class Button extends Component {
  render() {
    var css= "w3-btn w3-app-button w3-round";
    css += (this.props.size) ? " w3-"+this.props.size : "";
    return (
      <button onClick={this.props.proc} className={css}>{this.props.children}</button>
    );
  }
}
export const LoginButton = class LoginButton extends Component{
  render(){
    return(
      <Button proc={this.props.proc} size={this.props.size}>Sign In</Button>
    )
  }
}

我现在需要的是能够单击“登录”按钮,它会调用一个将进行一些后端通信的函数。我需要能够访问TextField状态以从该函数操纵errorflagerrormsg。显然我的方法是不正确的。但是,我发现很难找到一个可以效仿的例子。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

在这种情况下,正确的调用是传递函数回调作为道具(在本例中为proc)。

但是,当从下面的按钮向下调用loginUser时,类的上下文将不会绑定到函数上下文,从而使您无法使用组件的状态。

您可以通过在函数上调用.bind(this)或使其成为箭头函数来解决此问题:

  loginUser = ev => {
    //Call your backend here
    this.setState({ //No more undefined errors
      errorflage: true,
      errormsg: "This is a required Field"
    })
  }

我还建议您将按钮组件更改为无状态组件,因为它们不需要管理状态:

export function Button(props) {
    var css= "w3-btn w3-app-button w3-round";
    css += (this.props.size) ? " w3-"+this.props.size : "";
    return (
      <button onClick={props.proc} className={css}>{props.children}</button>
    );
}

export function LoginButton({ proc, size }) {
    return(
      <Button proc={proc} size={size}>Sign In</Button>
    )
}

简短版本:

const LoginButton = ({ proc, size }) => <Button proc={proc} size={size}>Sign In</Button>
export LoginButton