0

I am trying to get a very simple react app up-and-running.

The use case is straightforwards: An auto-complete component that gets an array of account names, and upon value changed (user has selected the value) - fire event that will display the account.

Here is a code snippet, which I am trying to get work in a way that showAccount method will have access to App's state.

How can I access App's state from showAccount() ?

import React, { Component } from 'react';
import injectTapEventPlugin from 'react-tap-event-plugin';

import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AutoComplete from 'material-ui/AutoComplete';


// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();

import './App.css';


class App extends Component {
  constructor () {
    super();
    this.state = {accounts: []}
  }

  componentDidMount() {
    this.setState({ accounts: [
      {account_name: "foo", account_id: 1},
      {account_name: "bar", account_id: 2}
    ]})
  }

  showAccount (value) {
    // HERE IS THE PROBLEM!
    // `this` points to AutoComplete rather than to App
    console.log(this.state.accounts)
  }

  render() {
    return (      
      <MuiThemeProvider>
        <div className="App">
        <center>
        <AutoComplete
          floatingLabelText="account name"
          filter={AutoComplete.caseInsensitiveFilter}
          dataSource={this.state.accounts.map((account) => account.account_name)}
          onUpdateInput={this.showAccount}
        /></center>
        </div>
      </MuiThemeProvider>
    );
  }
}

export default App;
Tzury Bar Yochay
  • 8,798
  • 5
  • 49
  • 73

2 Answers2

3

Don't you miss binding the showAccount method?

Check this code, there's an example of how to bind it, you need to do the same with your showAccount method.

class InputExample extends React.Component {
  constructor(props) {
    super(props);

    this.state = { text: '' };
    this.change = this.change.bind(this);
  }

  change(ev) {
    this.setState({ text: ev.target.value });
  }

  render() {
    let { text } = this.state;
    return (<input type="text" value={text} onChange={this.change} />);
  }
}

In ECMAScript 2015 classes you need to bind your methods manually.

I don't have time to expand more, because I'm at work, but check this article

http://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/ Check the ECMAScript 2015 classes section The sample code is from that post

Regards

Mauro Alvarez
  • 550
  • 6
  • 27
  • 1
    @Tzury Bar Yochay this is the corect way to do things - you should bind in the constructor and not in the render method otherwise you'll take a performance hit by binding every time the view is rendered – Jordan Nov 23 '16 at 18:12
1

bind your call to the App scope:

{ this.showAccount.bind(this) }

should work!

A Macdonald
  • 814
  • 1
  • 7
  • 10