this refs is getting undefined in method

2020-06-03 00:20发布

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>

3条回答
Evening l夕情丶
2楼-- · 2020-06-03 00:44

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.

查看更多
爷的心禁止访问
3楼-- · 2020-06-03 00:56

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/ )

查看更多
霸刀☆藐视天下
4楼-- · 2020-06-03 00:59

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()
}
查看更多
登录 后发表回答