cjmling
cjmling

Reputation: 7278

this refs is getting undefined in method

I am trying to use this plugin in my project https://github.com/rt2zz/react-native-drawer. I could run the example properly but having problem integrating it.

I am getting error in method openDrawer. "Can not read property drawer of undefined"

I am guessing that I am not defining and using the class in the right way as it should be ( i'm new to javascript OOP ) as in example it use React.createClass({ unlike mine as extending Component and have constructor.

Relevant codes from my class are as follow.

class Search extends Component {

    constructor(props) {
        super(props);
        this.state = {
            isLoading: true,
            dataSource: new ListView.DataSource({
               rowHasChanged: (row1, row2) => row1 !== row2
            })
        };
    }

    openDrawer(){
        this.refs.drawer.open()
    }

    getInitialState(){
        return {
          drawerType: 'overlay',

        }
    }

Render are

render() {
        if (this.state.isLoading) {
            return this.renderLoadingView();
        }

        var controlPanel = <MyControlPanel closeDrawer={() => {this.refs.drawer.close()}} />

        return (


            <View>
                <View style={styles.topBar}>

                    <Drawer
                        ref="drawer"
                        >
                        <MyMainView
                          />
                    </Drawer>

                    <Text style={styles.topBarMenu}>&#9776;</Text>
                    <Text style={styles.topBarTitle}>เงินปันผล</Text>
                    <Text style={styles.topBarRight}></Text>
                </View>

Upvotes: 15

Views: 21967

Answers (3)

zulucoda
zulucoda

Reputation: 858

Just to make it clear for everyone, when using ES6 class (instead of React.createClass) you have to bind methods to this in the constructor.

example

class Search extends Component {

    constructor(props) {
        super(props);

        this.state = {
            isLoading: true,
            dataSource: new ListView.DataSource({
               rowHasChanged: (row1, row2) => row1 !== row2
            })
        };

        this.openDrawer = this.openDrawer.bind(this); //bind this to openDrawer
    } 
}

Note: I thought I would add this answer since the answer that is marked as correct talks about reverting back to React.createClass. Also its been mentioned in the comments but not quite clear.

Upvotes: 5

Aleksandras
Aleksandras

Reputation: 595

There is a better way than putting this.openDrawer = this.openDrawer.bind(this) in constructor Declare openDrawer method with arrows function:

openDrawer = () => {
  this.refs.drawer.open()
}

Upvotes: 23

Jarek Potiuk
Jarek Potiuk

Reputation: 20077

I think it's best if you come back to using createClass . The ES6 way of creating classes (extends) has few disadvantages over createClass : the methods are unbound (i.e. "this" does not necessarily points to the object), also you cannot use mixins which are pretty useful. The unbound methods is the problem you are experiencing. You can also workaround it in case you have control over the place where the method is called and bind the method (look for method binding in javascript for example here: http://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/ )

Upvotes: 13

Related Questions