Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functions inside componentDidMount are undefined

I have the following block of code:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      avatar: '',
      ...some more data...
      }

      this.fetchUser = this.fetchUser.bind(this);
  }

  render() {
    return (
      <div>
        <SearchBox onSubmit={this.fetchUser}/>
        <Card data={this.state} />
        <BaseMap center={this.state.address}/>
      </div>
    );
  }

  componentDidMount() {
    function fetchUser(username) {
      let url = `https://api.github.com/users/${username}`;

      this.fetchApi(url);
    };

    function fetchApi(url) {
      fetch(url)
        .then((res) => res.json())
           .... some data that is being fetched .... 
        });
      };

    let url = `https://api.github.com/users/${this.state.username}`;
  }
}

export default App;

However, I get a TypeError: Cannot read property 'bind' of undefined for the following line: this.fetchUser = this.fetchUser.bind(this); in the constructor where I bind the function to this.

How can I make the function, which is inside componentDidMount method, visible and available for binding?

EDIT:

The reason I'm putting the functions inside componentDidMount was because of a suggestion from another user on StackOverflow. He suggested that:

@BirdMars that because you don't really fetch the data in the parent, and the state doesn't really hold the address object. call the fetch in componentDidMount of the parent and update the state there. this will trigger a second render that will pass in the new state with the address object (the first render will be with an empty state.address of course until you finish the fetch and update the state)

like image 568
birdybird03 Avatar asked Oct 08 '17 18:10

birdybird03


2 Answers

There is some fundamental misunderstanding here, you can still call the functions inside componentDidMount, however you should not define them inside it.

Simply define the functions outside componentDidMount and this will solve your problems, here is a short example

componentDidMount() {
   this.fetchUser(this.state.username);
}

function fetchUser(username) {
   let url = `https://api.github.com/users/${username}`;
   this.fetchApi(url);
};

function fetchApi(url) {
   fetch(url)
   .then((res) => res.json())
      .... some data that is being fetched .... 
   });
};
like image 181
Lyubomir Avatar answered Sep 21 '22 14:09

Lyubomir


Its a simple matter of scope:

function outer(){
  function inner(){
  }
}
inner(); // error does not exist

As birdmars suggested you should call this.fetchUser() inside component did mount. but declare the function outside!

class App extends Component {

  render() {
    return (
      <div>
        <SearchBox onSubmit={this.fetchUser}/>
        <Card data={this.state} />
        <BaseMap center={this.state.address}/>
      </div>
    );
  }
  fetchUser(username) {
      let url = `https://api.github.com/users/${username}`;

      this.fetchApi(url);
    };

  fetchApi(url) {
      fetch(url)
        .then((res) => res.json())
           .... some data that is being fetched .... 
        });
      };
  componentDidMount() {
    let url = username; //frome somewhere, most probably props then use props Changed function instead!
    var user = his.fetchUser(url)
    this.setState(() => {user: user});

  }
}

export default App;
like image 30
Joel Harkes Avatar answered Sep 24 '22 14:09

Joel Harkes