Sunny
Sunny

Reputation: 187

setState in Const Props ReactJS

I want to setstate of PageSearchByExcel's class but I know that (this) is no longer to PageSearchByExcel.

Have you some way to set state to a totalMatchSample variable.

I bring this code from ant-design Official web. https://ant.design/components/upload/

I'm very new to react.

Help me, please.

Or If you have another way that is better than this way please give it to me.

import ...

const props = {
  name: 'file',
  multiple: true,
  action: API_URL + '/api/search/excelfile',
  onChange(info) {
    const status = info.file.status;
    const data = new FormData()
    data.append('file', info.file.originFileObj, info.file.name)
    Axios.post(props.action, data)
      .then((Response) => {
        this.setState({
          totalMatchSample: info.file.response.length
        })
      })
  },
};

export default class PageSearchByExcel extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      totalSample: 0,
      totalMatchSample: 0
    }
  }

  render() {
    return (
      <div>
        <Dragger {...props}>
          <p className="ant-upload-drag-icon">
            <Icon type="inbox" />
          </p>
          <p className="ant-upload-text">Click or drag file to this area to upload</p>
          <p className="ant-upload-hint">Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files</p>
        </Dragger>
        <div>
          <p>
            {this.state.totalMatchSample} matched samples from 
            {this.state.totalSample} samples
              </p>
          <br />
        </div>
      </div>
    )
  }
}

Upvotes: 1

Views: 5188

Answers (2)

Hemant Parashar
Hemant Parashar

Reputation: 3774

Since you're declaring props outside the PageSearchByExcel component the this refers to props object itself and not the component. You can define the onChange method on the component and pass it down as a prop to Dragger which then will be correctly bound to PageSearchByExcel.

import ...

const props = {
  name: 'file',
  multiple: true,
  action: API_URL + '/api/search/excelfile',
};

export default class PageSearchByExcel extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      totalSample: 0,
      totalMatchSample: 0
    }
  }

  // Define onChange here
  onChange = (info) => {
    const status = info.file.status;
    const data = new FormData()
    data.append('file', info.file.originFileObj, info.file.name)
    Axios.post(props.action, data)
         .then((Response) => {
            this.setState({
              totalMatchSample: info.file.response.length
            })
          })
  }

  render() {
    return (
      <div>
        <Dragger {...props} onChange={this.onChange}>
          <p className="ant-upload-drag-icon">
            <Icon type="inbox" />
          </p>
          <p className="ant-upload-text">Click or drag file to this area to upload</p>
          <p className="ant-upload-hint">Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files</p>
        </Dragger>
        <div>
          <p>
            {this.state.totalMatchSample} matched samples from 
            {this.state.totalSample} samples
              </p>
          <br />
        </div>
      </div>
    )
  }
}

Hope this helps !

Upvotes: 2

Denis S Dujota
Denis S Dujota

Reputation: 611

@sun, based on what you posted, i will assume that you have some sort of props being passed to PageSearchByExcel component.

having said that, that props object, its an anti-pattern, you really want to pass each key in that props object to PageSearchByExcel down via the props system.

ex:

Class ParentComponent ... 
...some code 
render () {
..someJSX

<PageSearchByExcel name='file' multiple={true} />
}

this will basically setup your props inside PageSearchByExcel

now thats out of the way, let's talk about setState({}) and loading resources

in your PageSearchByExcel Component, you would have something like this



export default class PageSearchByExcel extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      totalSample: 0,
      totalMatchSample: 0
    }
  }

// define your axios call inside your component class NOT OUTSIDE

loadResource = () => {
 // ....yourAxiosCodeHere
}

// You then set the state at the first load of the component
componentDidMount () {
 this.loadResource()
}

  render() {
    return (
      <div>
        <Dragger {...this.props}>
          <p className="ant-upload-drag-icon">
            <Icon type="inbox" />
          </p>
          <p className="ant-upload-text">Click or drag file to this area to upload</p>
          <p className="ant-upload-hint">Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files</p>
        </Dragger>
        <div>
          <p>
            {this.state.totalMatchSample} matched samples from 
            {this.state.totalSample} samples
              </p>
          <br />
        </div>
      </div>
    )
  }
}

TAKEAWAY::

1.) define your class methods inside the class itself in order the properly reference 'this'

2.) make sure you pass the props down from the parent component down to your PageSearchByExcel

3.) make sure you load your resource using the react life cycle method

This should get you going.

Upvotes: 1

Related Questions