Search code examples
reactjsgsap

Is there a way to access a value computed using props in componentDidMount?


I'm working on converting a vanilla js gsap(GreenSock) animation to react, and want to access values based on props in componentDidMount(where gsap tweens are called). The animation is based on https://codepen.io/zadvorsky/pen/dILAG, using Delaunay triangulation and tweens to explode a shattered image. How do I access said values?

Originally I had the calculations contained in if(shatter) inside render but the values of rx, ry, and delay were undefined in the tween used in componentDidMount. I moved said calculations to componentDidMount so said values would be available, but the props are not available then, even with the use of a constructor.

export class Explosion extends React.Component {

constructor(props) {
    super(props)
    this.state = {
        shatter: false
    }
}

tl0 = new TimelineMax();
tl1 = new TimelineMax();


fragmentNode = React.createRef()
containerNode = React.createRef()

componentDidMount() {

    if (this.state.shatter) {
        const triangulatedValues = triangulate({
            this.props.width,
            this.props.height,
            this.props.startX,
            this.props.startY
        })

        const {
            vertices,
            indices
        } = triangulatedValues

        const ExplosionFragments = []

        for (let i = 0; i < indices.length; i += 3) {

            let point0 = vertices[indices[i + 0]]
            let point1 = vertices[indices[i + 1]]
            let point2 = vertices[indices[i + 2]]

            let fragmentCentroid = computeCentroid({
                point0,
                point1,
                point2
            })

            let dx = fragmentCentroid[0] - startX
            let dy = fragmentCentroid[1] - startY
            let d = Math.sqrt(dx * dx + dy * dy)
            let rx = -30 * sign(dy)
            let ry = -90 * -sign(dx)
            let delay = d * 0.003 * randomRange(0.7, 1.1)


            let box = computeBoundingBox({
                point0,
                point1,
                point2
            })

        }
    }

    this.tl1
        .to(this.fragmentNode, 1, {
            z:500,
            rotationX:rx,
            rotationY:ry,
            ease:Power2.easeInOut
        })
        .to(this.fragmentNode, 0.4,{alpha:0}, 1)
    this.tl0
        .insert(this.tl1, delay)
}

render() {

    const {
        shatter
    } = this.state



    return (
        <Container
            ref={this.containerNode}
            onClick={this.handleToggleShatter}
        >
            {shatter ? (
                <div>
                    <OverlayImage
                    src="http://i67.tinypic.com/2eq9utk.jpg"
                    />
                    <canvas
                    width={width}
                    height={height}
                    ref={this.fragmentRef}>
                    </canvas>
                </div>
            ) : (
                <OverlayImage
                    src="http://i67.tinypic.com/2eq9utk.jpg"
                />
            )}
        </Container>
    )
}
}

export default Explosion

https://codesandbox.io/s/ll139x3nx7

I expect the props to be available in componentDidMount, but the error "Parsing error: this is a reserved word" gets thrown. This is just an error for a possible solution, and I'm open to any way forward.


Solution

  • When you do:

    const triangulatedValues = triangulate({
        this.props.width,
        this.props.height,
        this.props.startX,
        this.props.startY
    })
    

    You're passing in an Object where the keys are this.props.width etc and the values are also this.props.width because you haven't specified any other key, so it'll try to call the key the name of the variable.

    Try:

    const triangulatedValues = triangulate({
        width: this.props.width,
        height: this.props.height,
        startX: this.props.startX,
        startY: this.props.startY
    })