Search code examples
reactjsrefgsap

Getting ref to dom object to access it in React


I'm playing with components that live by themselves, with styling and interaction all within the component. I'm trying to run a tween on a certain mouse event, I'm just playing now so ignore the mess. I can set the state in order to get at a dom node ref later, but when I try to call a function to then tween that TweenLite thinks the node to tween is null.

Any thoughts?

Thanks.

Oh, and when I do specifically pass the ref in as a property when calling the function, the function runs as soon as the component loads.

import React, {Component, PropTypes} from 'react';
var ReactDOM = require('react-dom');
var Stylesheet = require('react-style');

export default class Card extends Component {
    constructor(props) {
        super(props);
        //  Set state here if required.
        this.state = {Width: this.props.width, Height: this.props.height, cHeader:''};
    }

    componentDidMount() {
        //  This method is called when an instance of this component is created.
        console.log('New Card instance created.');
        this.setState({
            cHeader: this.refs.cardHeader
        });
    }

    render() {

        return (
            <div styles={[styles.card]}>
                <div ref="cardHeader" styles={[styles.cardHeader]} onClick={handleHeaderMouseEnter}></div>
            </div>
        )
    }
}

Card.propTypes = {width: React.PropTypes.number, height: React.PropTypes.number};
Card.defaultProps = {width: 350, height: 150};

function handleHeaderMouseEnter() {
    console.log("Did this run?");
    TweenLite.to(this.state.cHeader, 1, {css:{height:350}, ease:Power4.easeInOut});
}

var styles = Stylesheet.create({
    card: {
        overflow: 'hidden',
        width:350,
        height: 250,
        backgroundColor: '#E74C3C',
        borderRadius: 5,
        WebkitBoxShadow: "3px 3px 4px 1px rgba(196,196,196,1)",
        marginBottom: 25
    },
    cardHeader: {
        width: 350,
        height: 50,
        borderTopLeftRadius: 5,
        borderTopRightRadius: 5,
        backgroundColor: '#3498DB'
    }
})

I've updated the code as shown below, still no joy. TweenLite is still struggling to find the DOM node.

export default class Card extends Component {
    constructor(props) {
        super(props);
        //  Set state here if required.
        this.state = {Width: this.props.width, Height: this.props.height, cHeader:''};
    }

    componentDidMount() {
        //  This method is called when an instance of this component is created.
        console.log('New Card instance created.');
        this.setState({
            cHeader: (this.refs.cardHeader)
        });
    }

    render() {

        return (
            <div styles={[styles.card]}>
                <div ref="cardHeader" styles={[styles.cardHeader]} onClick={this.handleHeaderMouseEnter}></div>
            </div>
        )
    }

    handleHeaderMouseEnter() {
        console.log("Did this run?");
        TweenLite.to(React.findDOMNode(this.state.cHeader), 1, {css:{height:350}, ease:Power4.easeInOut});
    }
}

Solution

  • In you case you call handleHeaderMouseEnter outside of class Card, in this function this refers to global scope (in browser it window), and in window there is not property state - it is undefined. You should bind this to this function

    onClick={ handleHeaderMouseEnter.bind(this) }
    

    also if you move handleHeaderMouseEnter to class you also need set this to this method,

    onClick={ this.handleHeaderMouseEnter.bind(this) }
    

    Example