admin管理员组

文章数量:1022679

I know this question is getting asked a lot and I did check most of the other answers provided but I still can't find out why I get this error.

Situation:

I have my textinput class in which I have a simple form for the user to input a name. When the user submits the button a REST call to my backend is called and the UI should show the user's name.

I have overridden the function ponentDidMount of my App class to have an initial call to my backend when the page is loaded. This call works and I get the correct answer from my backend and the UI gets updated.

But when i make the call from my TextInput class, I get the error:

this2.setState is not a function

I believe that this is happening because I call the function from another class and the this state is not set correctly. I tried to bind all the things but that did not change anything. If anyone has an idea of what I am doing wrong, it would be very helpful!

I have the following classes:

import React, { Component } from 'react';
import logo from './logo.svg';
import Greeting from './ponents/greeting';
import TextInput from './ponents/textInput';
import './App.css';

const axios = require('axios');

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {name: "World"};
    this.getFormattedNameFromBackend.bind(this);
    this.setState.bind(this);
  }

  ponentDidMount() {
    this.getFormattedNameFromBackend(this.state.name);
  }

  getFormattedNameFromBackend(name) {
    axios({
      method:'get',
      url:'http://localhost:8080/hello?name=' + name
    }).then((response) => {
      this.setState({ name : response.data.name});
    }).catch(function(error){
      console.log(error);
    });
  }


  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <Greeting data={this.state}/>
          <TextInput callBack = {this.getFormattedNameFromBackend}/>
        </header>
      </div>
    );
  }

}

export default App;

This is the main class where I get the error in the axios rest call.

the second class is this:

import React, { Component } from 'react';

export default class TextInput extends Component {
    constructor(props) {
      super(props);
      this.state = {value: ''};

      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
    }

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

    handleSubmit(event) {
      this.props.callBack(this.state.value);

      event.preventDefault();
    }

    render() {
      return (
        <form onSubmit= {this.handleSubmit}>
          <label>
            Name:
            <input type="text" value={this.state.value} onChange={this.handleChange} />
          </label>
          <input type="submit" value="Submit" />
        </form>
      );
    }
  }

so the Question is, how do i call the correct this in the method getFormattedNameFromBackend?

Solved:

the mistake was setting the props of the Textinputfield wrong. Correctly it should be

<TextInput callBack = {(name)=>this.getFormattedNameFromBackend(name)}/>

I know this question is getting asked a lot and I did check most of the other answers provided but I still can't find out why I get this error.

Situation:

I have my textinput class in which I have a simple form for the user to input a name. When the user submits the button a REST call to my backend is called and the UI should show the user's name.

I have overridden the function ponentDidMount of my App class to have an initial call to my backend when the page is loaded. This call works and I get the correct answer from my backend and the UI gets updated.

But when i make the call from my TextInput class, I get the error:

this2.setState is not a function

I believe that this is happening because I call the function from another class and the this state is not set correctly. I tried to bind all the things but that did not change anything. If anyone has an idea of what I am doing wrong, it would be very helpful!

I have the following classes:

import React, { Component } from 'react';
import logo from './logo.svg';
import Greeting from './ponents/greeting';
import TextInput from './ponents/textInput';
import './App.css';

const axios = require('axios');

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {name: "World"};
    this.getFormattedNameFromBackend.bind(this);
    this.setState.bind(this);
  }

  ponentDidMount() {
    this.getFormattedNameFromBackend(this.state.name);
  }

  getFormattedNameFromBackend(name) {
    axios({
      method:'get',
      url:'http://localhost:8080/hello?name=' + name
    }).then((response) => {
      this.setState({ name : response.data.name});
    }).catch(function(error){
      console.log(error);
    });
  }


  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <Greeting data={this.state}/>
          <TextInput callBack = {this.getFormattedNameFromBackend}/>
        </header>
      </div>
    );
  }

}

export default App;

This is the main class where I get the error in the axios rest call.

the second class is this:

import React, { Component } from 'react';

export default class TextInput extends Component {
    constructor(props) {
      super(props);
      this.state = {value: ''};

      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
    }

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

    handleSubmit(event) {
      this.props.callBack(this.state.value);

      event.preventDefault();
    }

    render() {
      return (
        <form onSubmit= {this.handleSubmit}>
          <label>
            Name:
            <input type="text" value={this.state.value} onChange={this.handleChange} />
          </label>
          <input type="submit" value="Submit" />
        </form>
      );
    }
  }

so the Question is, how do i call the correct this in the method getFormattedNameFromBackend?

Solved:

the mistake was setting the props of the Textinputfield wrong. Correctly it should be

<TextInput callBack = {(name)=>this.getFormattedNameFromBackend(name)}/>
Share Improve this question edited Nov 11, 2018 at 14:25 Marcus Lanvers asked Nov 11, 2018 at 13:48 Marcus LanversMarcus Lanvers 4116 silver badges21 bronze badges 7
  • Sounds like this is referencing the wrong object. Try printing what this is where it raises, or reading this stackoverflow./questions/45041878/closures-in-react In short, events in render function act on event objects and not on the class that the render function is defined on, that is because events are async... – Daniel Dror Commented Nov 11, 2018 at 13:56
  • at the time i get the error "this" is an object of type textinput. But how to i change that? – Marcus Lanvers Commented Nov 11, 2018 at 13:58
  • Try looking at the link I provided, easiest way would be to bind it via closure onSubmit= (e) => {this.handleSubmit(e)}. Take a look at this as well : reactjs/docs/handling-events.html – Daniel Dror Commented Nov 11, 2018 at 13:59
  • i am trying this but that actually gives me syntax errors. :/ I am trying this now: onSubmit={(e)=>this.handleSubmit(e)} but that gives me the same error i had before – Marcus Lanvers Commented Nov 11, 2018 at 14:03
  • 1 take a look at this, it seems to be working jsfiddle/n5u2wwjg/233958 – Daniel Dror Commented Nov 11, 2018 at 14:18
 |  Show 2 more ments

2 Answers 2

Reset to default 4

In case anyone else reaches this question, https://reactjs/docs/handling-events.html explains quite well why this happens.

In short, this is not bound when event callbacks are invoked.

The easiest way to fix this is by enclosing this : onSubmit={(e) => {this.handleSubmit(e)} (altough this does create a new function instance each time, so need to be careful when using this method).

The way you solved it works by simply avoiding the binding if this altogether, but your original problem was that the line

    this.getFormattedNameFromBackend.bind(this);

doesn't do exactly what you think it does.
.bind() returns a new function that wraps the original function, but you're not doing anything with that new function. .bind() doesn't modify the original function so this.getFormattedNameFromBackend remains unbound and that's why <TextInput callBack = {this.getFormattedNameFromBackend}/> didn't work.

If you had written that line as:

    this.getFormattedNameFromBackend = this.getFormattedNameFromBackend.bind(this);

...(like you do in your TextInput class) it would get bound properly and callBack = {this.getFormattedNameFromBackend} would work.

Like I said, by writing it as callBack = {() => this.getFormattedNameFromBackend()} you're avoiding the binding issue anyway so you can simply remove this.getFormattedNameFromBackend.bind(this); (and BTW, this.setState.bind(this); is pretty pointless too)

I know this question is getting asked a lot and I did check most of the other answers provided but I still can't find out why I get this error.

Situation:

I have my textinput class in which I have a simple form for the user to input a name. When the user submits the button a REST call to my backend is called and the UI should show the user's name.

I have overridden the function ponentDidMount of my App class to have an initial call to my backend when the page is loaded. This call works and I get the correct answer from my backend and the UI gets updated.

But when i make the call from my TextInput class, I get the error:

this2.setState is not a function

I believe that this is happening because I call the function from another class and the this state is not set correctly. I tried to bind all the things but that did not change anything. If anyone has an idea of what I am doing wrong, it would be very helpful!

I have the following classes:

import React, { Component } from 'react';
import logo from './logo.svg';
import Greeting from './ponents/greeting';
import TextInput from './ponents/textInput';
import './App.css';

const axios = require('axios');

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {name: "World"};
    this.getFormattedNameFromBackend.bind(this);
    this.setState.bind(this);
  }

  ponentDidMount() {
    this.getFormattedNameFromBackend(this.state.name);
  }

  getFormattedNameFromBackend(name) {
    axios({
      method:'get',
      url:'http://localhost:8080/hello?name=' + name
    }).then((response) => {
      this.setState({ name : response.data.name});
    }).catch(function(error){
      console.log(error);
    });
  }


  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <Greeting data={this.state}/>
          <TextInput callBack = {this.getFormattedNameFromBackend}/>
        </header>
      </div>
    );
  }

}

export default App;

This is the main class where I get the error in the axios rest call.

the second class is this:

import React, { Component } from 'react';

export default class TextInput extends Component {
    constructor(props) {
      super(props);
      this.state = {value: ''};

      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
    }

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

    handleSubmit(event) {
      this.props.callBack(this.state.value);

      event.preventDefault();
    }

    render() {
      return (
        <form onSubmit= {this.handleSubmit}>
          <label>
            Name:
            <input type="text" value={this.state.value} onChange={this.handleChange} />
          </label>
          <input type="submit" value="Submit" />
        </form>
      );
    }
  }

so the Question is, how do i call the correct this in the method getFormattedNameFromBackend?

Solved:

the mistake was setting the props of the Textinputfield wrong. Correctly it should be

<TextInput callBack = {(name)=>this.getFormattedNameFromBackend(name)}/>

I know this question is getting asked a lot and I did check most of the other answers provided but I still can't find out why I get this error.

Situation:

I have my textinput class in which I have a simple form for the user to input a name. When the user submits the button a REST call to my backend is called and the UI should show the user's name.

I have overridden the function ponentDidMount of my App class to have an initial call to my backend when the page is loaded. This call works and I get the correct answer from my backend and the UI gets updated.

But when i make the call from my TextInput class, I get the error:

this2.setState is not a function

I believe that this is happening because I call the function from another class and the this state is not set correctly. I tried to bind all the things but that did not change anything. If anyone has an idea of what I am doing wrong, it would be very helpful!

I have the following classes:

import React, { Component } from 'react';
import logo from './logo.svg';
import Greeting from './ponents/greeting';
import TextInput from './ponents/textInput';
import './App.css';

const axios = require('axios');

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {name: "World"};
    this.getFormattedNameFromBackend.bind(this);
    this.setState.bind(this);
  }

  ponentDidMount() {
    this.getFormattedNameFromBackend(this.state.name);
  }

  getFormattedNameFromBackend(name) {
    axios({
      method:'get',
      url:'http://localhost:8080/hello?name=' + name
    }).then((response) => {
      this.setState({ name : response.data.name});
    }).catch(function(error){
      console.log(error);
    });
  }


  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <Greeting data={this.state}/>
          <TextInput callBack = {this.getFormattedNameFromBackend}/>
        </header>
      </div>
    );
  }

}

export default App;

This is the main class where I get the error in the axios rest call.

the second class is this:

import React, { Component } from 'react';

export default class TextInput extends Component {
    constructor(props) {
      super(props);
      this.state = {value: ''};

      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
    }

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

    handleSubmit(event) {
      this.props.callBack(this.state.value);

      event.preventDefault();
    }

    render() {
      return (
        <form onSubmit= {this.handleSubmit}>
          <label>
            Name:
            <input type="text" value={this.state.value} onChange={this.handleChange} />
          </label>
          <input type="submit" value="Submit" />
        </form>
      );
    }
  }

so the Question is, how do i call the correct this in the method getFormattedNameFromBackend?

Solved:

the mistake was setting the props of the Textinputfield wrong. Correctly it should be

<TextInput callBack = {(name)=>this.getFormattedNameFromBackend(name)}/>
Share Improve this question edited Nov 11, 2018 at 14:25 Marcus Lanvers asked Nov 11, 2018 at 13:48 Marcus LanversMarcus Lanvers 4116 silver badges21 bronze badges 7
  • Sounds like this is referencing the wrong object. Try printing what this is where it raises, or reading this stackoverflow./questions/45041878/closures-in-react In short, events in render function act on event objects and not on the class that the render function is defined on, that is because events are async... – Daniel Dror Commented Nov 11, 2018 at 13:56
  • at the time i get the error "this" is an object of type textinput. But how to i change that? – Marcus Lanvers Commented Nov 11, 2018 at 13:58
  • Try looking at the link I provided, easiest way would be to bind it via closure onSubmit= (e) => {this.handleSubmit(e)}. Take a look at this as well : reactjs/docs/handling-events.html – Daniel Dror Commented Nov 11, 2018 at 13:59
  • i am trying this but that actually gives me syntax errors. :/ I am trying this now: onSubmit={(e)=>this.handleSubmit(e)} but that gives me the same error i had before – Marcus Lanvers Commented Nov 11, 2018 at 14:03
  • 1 take a look at this, it seems to be working jsfiddle/n5u2wwjg/233958 – Daniel Dror Commented Nov 11, 2018 at 14:18
 |  Show 2 more ments

2 Answers 2

Reset to default 4

In case anyone else reaches this question, https://reactjs/docs/handling-events.html explains quite well why this happens.

In short, this is not bound when event callbacks are invoked.

The easiest way to fix this is by enclosing this : onSubmit={(e) => {this.handleSubmit(e)} (altough this does create a new function instance each time, so need to be careful when using this method).

The way you solved it works by simply avoiding the binding if this altogether, but your original problem was that the line

    this.getFormattedNameFromBackend.bind(this);

doesn't do exactly what you think it does.
.bind() returns a new function that wraps the original function, but you're not doing anything with that new function. .bind() doesn't modify the original function so this.getFormattedNameFromBackend remains unbound and that's why <TextInput callBack = {this.getFormattedNameFromBackend}/> didn't work.

If you had written that line as:

    this.getFormattedNameFromBackend = this.getFormattedNameFromBackend.bind(this);

...(like you do in your TextInput class) it would get bound properly and callBack = {this.getFormattedNameFromBackend} would work.

Like I said, by writing it as callBack = {() => this.getFormattedNameFromBackend()} you're avoiding the binding issue anyway so you can simply remove this.getFormattedNameFromBackend.bind(this); (and BTW, this.setState.bind(this); is pretty pointless too)

本文标签: javascriptReact TypeError quotthis2setState is not a functionquotStack Overflow