1

I am trying to create a simple react form to submit data to a webapi, however I get this error

Unhandled Rejection (TypeError): Cannot read property 'tenantid' of undefined
./src/containers/RegisterTenant/register.js
src/containers/RegisterTenant/register.js:13
  10 | import { adalApiFetch } from '../../adalConfig';
  11 | 
  12 | const data = {
> 13 |   TenantId: this.state.tenantid,
  14 |   TenanrUrl: this.state.tenanturl,
  15 |   TenantPassword: this.state.tenantpassword 
  16 | };

My code is like this:

import React, { Component } from 'react';

import { Row, Col } from 'antd';
import PageHeader from '../../components/utility/pageHeader';
import Box from '../../components/utility/box';
import LayoutWrapper from '../../components/utility/layoutWrapper.js';
import ContentHolder from '../../components/utility/contentHolder';
import basicStyle from '../../settings/basicStyle';
import IntlMessages from '../../components/utility/intlMessages';
import { adalApiFetch } from '../../adalConfig';

const data = {
  TenantId: this.state.tenantid,
  TenanrUrl: this.state.tenanturl,
  TenantPassword: this.state.tenantpassword 
};

const options = {
  method: 'post',
  data: data,
  config: {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  }
};

export default class extends Component {
  constructor(props) {
    super(props);
    this.state = {TenantId: '',TenanrUrl:'',TenantPassword:''};
    this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
    this.handleChangeTenantPassword = this.handleChangeTenantPassword.bind(this);
    this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChangeTenantUrl(event){
    this.setState({tenanturl: event.target.value});
  }

  handleChangeTenantPassword(event){
    this.setState({tenantpassword: event.target.value});
  }

  handleChangeTenantId(event){
    this.setState({tenantid: event.target.value});
  }

  handleSubmit(event){
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
    this.data.append("TenantId", this.state.tenantid);
    this.data.append("TenanrUrl", this.state.tenanturl);
    this.data.append("TenantPassword", this.state.tenantpassword);

    const options = {
      method: 'post',
      data: this.data,
      config: {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }
    };

    adalApiFetch(options)
      .then(response => response.json())
      .then(responseJson => {
        if (!this.isCancelled) {
          this.setState({ data: responseJson });
        }
      })
      .catch(error => {
        console.error(error);
      });
  }



  upload(e){
      let data = new FormData();
      //Append files to form data
      let files = e.target.files;
      for (let i = 0; i < files.length; i++) {
        data.append('files', files[i], files[i].name);
      }      
  }

  render(){
    const { data } = this.state;
    const { rowStyle, colStyle, gutter } = basicStyle;

    return (
      <div>
        <LayoutWrapper>
        <PageHeader>{<IntlMessages id="pageTitles.TenantAdministration" />}</PageHeader>
        <Row style={rowStyle} gutter={gutter} justify="start">
          <Col md={12} sm={12} xs={24} style={colStyle}>
            <Box
              title={<IntlMessages id="pageTitles.TenantAdministration" />}
              subtitle={<IntlMessages id="pageTitles.TenantAdministration" />}
            >
              <ContentHolder>
              <form onSubmit={this.handleSubmit}>
                <label>
                  TenantId:
                  <input type="text" value={this.state.tenantid} onChange={this.handleChangeTenantId} />
                </label>
                <label>
                  TenantUrl:
                  <input type="text" value={this.state.tenanturl} onChange={this.handleChangeTenantUrl} />
                </label>
                <label>
                  TenantPassword:
                  <input type="text" value={this.state.tenantpassword} onChange={this.handleChangeTenantPassword} />
                </label>
                <label>
                  Certificate:
                  <input onChange = { e => this.upload(e) } type = "file" id = "files" ref = { file => this.fileUpload } />
                </label>             
              <input type="submit" value="Submit" />
              </form>
              </ContentHolder>
            </Box>
          </Col>
        </Row>
      </LayoutWrapper>
      </div>
    );
  }
}
Luis Valencia
  • 32,619
  • 93
  • 286
  • 506
  • 1
    You are using `this.state.tenantid` outside of your component. – Tholle Jul 15 '18 at 20:08
  • so, if I initialize it to empty strings, its ok? – Luis Valencia Jul 15 '18 at 20:37
  • Yes, you can't access a component's state outside of the component. You don't seem to be using `data` or `options` that are outside of the component anywhere though. Are you sure you need those? – Tholle Jul 15 '18 at 20:39

1 Answers1

1

This is a problem of scope. In your example this.state is undefined because this is referring to the global scope, or undefined if you're in strict mode. It needs to be moved inside of the component, so that this is set to the instance of the component. You can either use class instance property, or move it within the class constructor.

There is another issue inside of your render() function where you're destructuring this.state and grabbing the data value, however there is no data key on this.state. Refer to the constructor.

newswim
  • 430
  • 3
  • 7