1

Exploring ReactJS and I have run into a conundrum. I have a child component that contains a TextField component and a Button component:

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 Component:

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>
    );
  };
}

Button Component:

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>
    )
  }
}

What I need now is to be able to click the Sign In button and it calls a function that will do some backend communication. I need to be able to access the TextField states to manipulate the errorflag and errormsg from that function. Obviously my approach is not correct; however, I am finding it difficult to find an example to follow. Any help would be appreciated.

Treycos
  • 7,373
  • 3
  • 24
  • 47
Elcid_91
  • 1,571
  • 4
  • 24
  • 50
  • So do you need Button to be able to access something in the state of TextField? Also, just as a tip, you can export a class directly, you don't need to make a const. So you can say 'export class LoginButton extends Component' – DanBonehill Aug 08 '19 at 13:29
  • 1
    Possible duplicate of [How to update parent's state in React?](https://stackoverflow.com/questions/35537229/how-to-update-parents-state-in-react) – vivalldi Aug 08 '19 at 13:40

1 Answers1

0

Passing a function callback as a prop (in this case named proc) is the right call in this situation.

However, when your loginUser will be called from the button down below, the context of the class will not be bound to the function context, making you unable to use the component's state.

You can solve this by calling .bind(this) on your function or by making it an arrow function :

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

I would also recommend changing your button components to stateless ones, as they do not need to manage a state :

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>
    )
}

Short version :

const LoginButton = ({ proc, size }) => <Button proc={proc} size={size}>Sign In</Button>
export LoginButton
Treycos
  • 7,373
  • 3
  • 24
  • 47