1

I am new to react. I am unable to figure out how to make this work.

This [Refs to Component]

ref={(node) => {this.loginMobileInput = node}}

gives me error

Uncaught (in promise) TypeError: Cannot set property 'loginMobileInput' of undefined
    at ref (eval at ./app/containers/Login/index.js ...

when returned with the component

<Input
      style={{marginTop: "5%"}}
      size="large"
      placeholder="Enter your mobile number"
      prefix={<Icon type="mobile" />}
      suffix={suffix}
      value={loginMobile}
      onChange={onChangeLoginMobile}
      ref={(node) => {this.loginMobileInput = node}} 
     />

inside this function on some condition

function LoginScreen(props) {}

When I use it directly [without any conditional rendering ie directly inside render()] it just runs without any error. I assume there is some this scope error, but I have no clue how to solve this. What I think is this scope inside render(return(//here)) and this scope inside function(){return(//here)} are different.

When I try to use it in this below way it gives no error but on every change to input my input focus is out. But when using it inside render(return(//directly here with component)) it works perfectly fine.

let loginMobileInput = this.loginMobileInput;

    function LoginScreen(props) {

      const user = props.user;
      if (user) {
        return <User user={user}/>;
      }
      else{
        return <div>
                <div style={{width:"100%",textAlign:"center",marginBottom: "3%",fontFamily: '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'+" !important"}}>
                  <p>Get Started</p>
                  <p>Enter your details to continue</p>
                </div>
                <Card>
                  <Input
                    style={{marginTop: "5%"}}
                    size="large"
                    placeholder="Enter your mobile number"
                    prefix={<Icon type="mobile" />}
                    suffix={suffix}
                    value={loginMobile}
                    onChange={onChangeLoginMobile}
                    ref={(node) => {loginMobileInput = node}}
                  />
                  <Button onClick={onSubmitLoginMobile} style={{width:"100%", marginTop:"6%"}} size="large" type="default">Continue</Button>
                </Card>
              </div>
      }

      return null;
    }

What ref actually need is unclear to me. I read the docs but I dont know how to use it in this scenario. I am using antd as the components library which I think has no relation to this error.

I hope I have asked my question correctly. Please help me out with this.

Below is the entire code I am running.

export class Login extends React.Component { // eslint-disable-line react/prefer-stateless-function

  render() {

    const { loginMobile, user, userCheckRequest } = this.props;
    const { onChangeLoginMobile, onSubmitLoginMobile } = this.props;

    const suffix = loginMobile ? <Icon type="close-circle" onClick={this.props.clearMobile} /> : null;

    function LoginScreen(props) { 

      const user = props.user;
      if (user) {
        return <User user={user}/>;
      }
      else{
        return <div>
                <div style={{width:"100%",textAlign:"center",marginBottom: "3%",fontFamily: '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'+" !important"}}>
                  <p>Get Started</p>
                  <p>Enter your details to continue</p>
                </div>
                <Card>
                  <Input
                    style={{marginTop: "5%"}}
                    size="large"
                    placeholder="Enter your mobile number"
                    prefix={<Icon type="mobile" />}
                    suffix={suffix}
                    value={loginMobile}
                    onChange={onChangeLoginMobile}
                    ref={(node) => {this.loginMobileInput = node}} // HERE IT THROWS AN ERROR
                  />
                  <Button onClick={onSubmitLoginMobile} style={{width:"100%", marginTop:"6%"}} size="large" type="default">Continue</Button>
                </Card>
              </div>
      }

      return null;
    }

    return (
      <div>
        <HeaderLarge />
        <Row style={{marginTop: "5%"}}>
          <Col span={9}></Col>
          <Col span={6}>
              <LoginScreen user={user}/>
          </Col>
          <Col span={9}></Col>
        </Row>
        <Row>
          <Col span={9}></Col>
          <Col span={6}>
          </Col>
          <Col span={9}></Col>
        </Row>
      </div>
    );
  }
}

const mapStateToProps = createStructuredSelector({
  loginMobile: loginMobileSelector(),
  user: userSelector(),
  userCheckRequest: userCheckRequestSelector(),
});

export function mapDispatchToProps(dispatch) {
  return {
    onChangeLoginMobile: (evt) => dispatch(changeMobile(evt.target.value)),
    clearMobile: () => dispatch(clearMobile()),
    onSubmitLoginMobile: () => dispatch(checkUserRequested())
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Login);
Ghost
  • 63
  • 1
  • 8

1 Answers1

0

You don't usually need to use ref, and I think antd doesn't expose the ref props. and most probably don't need it.

Uncaught (in promise) TypeError: Cannot set property 'loginMobileInput' of undefined
    at ref (eval at ./app/containers/Login/index.js ...

just means the the this.loginMobileInput is undefined, which you can not asign something to undefined

I'm not sure what you are trying to do with

ref={(node) => {this.loginMobileInput = node}}

Yichz
  • 9,250
  • 10
  • 54
  • 92
  • 1
    To me its this It cannot set property of undefined object. That undefined object is `this` whose property `loginMobile` it cannot set. I was asking what this `this` refers to here. I added this `componentDidMount(){ this.loginMobileInput.focus(); }` Its working now. Why was it required here ?. The input field was going out of focus on each render. I am still exploring what is it actually. – Ghost Jun 16 '17 at 07:56