wagerfield / parallax

Parallax Engine that reacts to the orientation of a smart device
http://wagerfield.github.io/parallax/
Other
16.48k stars 2.14k forks source link

How can I use Parallax.js with React.js? #167

Closed JoeyCurry closed 7 years ago

JoeyCurry commented 7 years ago

How can I use Parallax.js with React.js?

reneroth commented 7 years ago

The same way you use any external JS library with React :) require, and then hook it, for example in your componentWillMount method

wagerfield commented 7 years ago

Thanks for taking the time to help everyone out @RRorg.

@JoeyCurry please see below:

import React, { Component } from 'react'
import Parallax from 'parallax-js' // Now published on NPM

class ParallaxComponent extends Component {
  componentDidMount() {
    this.parallax = new Parallax(this.scene)
  }
  componentWillUnmount() {
    this.parallax.disable()
  }
  render() {
    render (
      <ul ref={el => this.scene = el}>
        <li className="layer" dataDepth="0.00">
          <img src="layer1.png"/>
        </li>
        <li className="layer" dataDepth="0.50">
          <img src="layer2.png"/>
        </li>
        <li className="layer" dataDepth="1.00">
          <img src="layer3.png"/>
        </li>
      </ul>
    )
  }
}
raj-khare commented 6 years ago

Why it's not working?

Could not find a declaration file for module 'parallax-js'. '/Users/stuff/Desktop/portfolio/node_modules/parallax-js/dist/parallax.js' implicitly has an 'any' type.
Try `npm install @types/parallax-js` if it exists or add a new declaration (.d.ts) file containing `declare module 'parallax-js';`
reneroth commented 6 years ago

@pixzels set noImplicitAny to false in your typescript configuration. If you still face problems after that, please open a new issue and contribute as much information as possible.

brybrophy commented 6 years ago

@pixzels It isn't working because there are no TypeScript type definitions for this package.

In the error message it says you can

add a new declaration (.d.ts) file containing declare module 'parallax-js';

I would suggest going this route, rather than setting noImplicitAny=false in your TypeScript config. If you really want to get the most power out of TypeScript, you want your config to be as strict as possible.

Harti commented 6 years ago

@brybrophy where do you suggest such a file should be added, and what should its contents be precisely?

majidzeno commented 6 years ago

when I tried to console.log(this.scene) it returns undefined, I wrapped it in an if condition and it still returns undefined

reneroth commented 6 years ago

@majidzeno please make some effort in helping us help you

On 26. Sep 2018, at 15:05, Majid Eltayeb notifications@github.com wrote:

when I tried to console.log(this.scene) it returns undefined, I wrapped it in an if condition and it still returns undefined

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/wagerfield/parallax/issues/167#issuecomment-424707390, or mute the thread

majidzeno commented 6 years ago

@reneroth I used npm i -s parallax-js and inside my component, I did the same thing like that quoted reply, I added ref={el => this.scene = el} to my component and inside componentDidMount i tried to cosole.log(this.scene) and i got undefined P.S: My component is fetched from Wordpress API ... I think that could be the cause

Thanks for taking the time to help everyone out @RRorg.

@JoeyCurry please see below:

import React, { Component } from 'react'
import Parallax from 'parallax-js' // Now published on NPM

class ParallaxComponent extends Component {
  componentDidMount() {
    this.parallax = new Parallax(this.scene)
  }
  componentWillUnmount() {
    this.parallax.disable()
  }
  render() {
    render (
      <ul ref={el => this.scene = el}>
        <li className="layer" dataDepth="0.00">
          <img src="layer1.png"/>
        </li>
        <li className="layer" dataDepth="0.50">
          <img src="layer2.png"/>
        </li>
        <li className="layer" dataDepth="1.00">
          <img src="layer3.png"/>
        </li>
      </ul>
    )
  }
}
majidzeno commented 6 years ago

@reneroth Okay I solved the issue , I was fetching posts from API and I was trying to apply parallax to every single post , I used the solution that @wagerfield introduced, the issue was the refs, in React 16.3 it is recommended to use React.createRef() API and also after using ref it returns a node so to access the dom element you have to use current, to access all posts I had to give the posts container a ref and then loop through its children and give every single post a parallax in componentDidUpdate .. check out my component


import React, { Component } from "react";
import Parallax from "parallax-js";
class Diary extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.scene = React.createRef();
  }

  componentDidUpdate() {
    if (this.scene) {
      var childNodes = this.scene.current.childNodes;
      var i;
      for (i = 0; i < childNodes.length; i++) {
        this.parallax = new Parallax(childNodes[i]);
      }
    } else {
      return null;
    }
  }
  componentWillUnmount() {
    this.parallax.disable();
  }

  render() {
    if (!this.state.pageData) return null;
    const posts = this.state.pageData.map((post, index) => {
      return (
        <div
          key={index}
          className="post diary-post"
          data-relative-input="true"
          data-hover-only="true"
          data-clip-relative-input="true">
          <div className="diary-post__background" data-depth="0.4">
            <figure
              data-depth="0.6"
              className="diary-post__image"
              style={{
                backgroundImage: `url(${
                  post._embedded["wp:featuredmedia"][0].media_details.sizes
                    .medium.source_url
                })`
              }}
            />
          </div>
          <h2 className="diary-post__title" data-depth="0.4">
            {post.title.rendered}
          </h2>
          <h6 className="diary-post__date">{post.date}</h6>
        </div>
      );
    });
    return (
      <main ref={this.scene} className="page page-diary">
        {posts}
      </main>
    );
  }
}
export default Diary;
reneroth commented 6 years ago

Thank you for sharing your solution! :)

On 27. Sep 2018, at 14:18, Majid Eltayeb notifications@github.com wrote:

@reneroth https://github.com/reneroth Okay I solved the issue , I was fetching posts from API and I was trying to apply parallax to every single post , I used the solution that @wagerfield https://github.com/wagerfield introduced, the issue was the refs, in React 16.3 it is recommended to use React.createRef() API and also after using ref it returns a node so to access the dom element you have to use current, to access all posts I had to give the posts container a ref and then loop through its children and give every single post a parallax in componentDidUpdate .. check out my component `import React, { Component } from "react"; import Parallax from "parallax-js"; class Diary extends Component { constructor(props) { super(props); this.state = {}; this.scene = React.createRef(); }

componentDidUpdate() { if (this.scene) { var childNodes = this.scene.current.childNodes; var i; for (i = 0; i < childNodes.length; i++) { this.parallax = new Parallax(childNodes[i]); } } else { return null; } } componentWillUnmount() { this.parallax.disable(); }

render() { if (!this.state.pageData) return null; const posts = this.state.pageData.map((post, index) => { return (

<figure data-depth="0.6" className="diary-post__image" style={{ backgroundImage: url(${ post._embedded["wp:featuredmedia"][0].media_details.sizes .medium.source_url }) }} />

{post.title.rendered}

{post.date}

); }); return (

{posts}

); } } export default Diary; `

xavierartot commented 5 years ago

I switched to React library, a tons are much better for a SAP. https://www.npmjs.com/package/rc-scroll-anim https://www.npmjs.com/package/react-plx etc...

kingdavidmartins commented 4 years ago

Updated with hook version for those who are curious.

const YourComponent = () => {
  const sceneEl = useRef(null);

  useEffect(() => {
    const parallaxInstance = new Parallax(sceneEl.current, {
      relativeInput: true,
      hoverOnly: true
    })

    parallaxInstance.enable();

    return () => parallaxInstance.disable();
  }, [])

  return (
    <div ref={sceneEl}>
      {/* html */}
    </div>
  )
}
fleece30 commented 3 years ago

Updated with hook version for those who are curious.

const YourComponent = () => {
  const sceneEl = useRef(null);

  useEffect(() => {
    const parallaxInstance = new Parallax(sceneEl.current, {
      relativeInput: true,
      hoverOnly: true
    })

    parallaxInstance.enable();

    return () => parallaxInstance.disable();
  }, [])

  return (
    <div ref={sceneEl}>
      {/* html */}
    </div>
  )
}

The sceneEl.current is always null for some reason so parallax doesnt understand what it is and throws an error. I tried to do it using getElementById but it just messes up the design of the app and doesnt apply the parallax effect.

ArmedVeteran commented 3 years ago

Updated with hook version for those who are curious.

const YourComponent = () => {
  const sceneEl = useRef(null);

  useEffect(() => {
    const parallaxInstance = new Parallax(sceneEl.current, {
      relativeInput: true,
      hoverOnly: true
    })

    parallaxInstance.enable();

    return () => parallaxInstance.disable();
  }, [])

  return (
    <div ref={sceneEl}>
      {/* html */}
    </div>
  )
}

The sceneEl.current is always null for some reason so parallax doesnt understand what it is and throws an error. I tried to do it using getElementById but it just messes up the design of the app and doesnt apply the parallax effect.

The solution posted by @kingdavidmartins works well. Are you sure sceneEl.current is the problem? I've had a mistake in my code, because I've been looking at the original answer and there's an attribute spelling mistake (made due to the React standard) - it should be "data-depth", instead of "dataDepth". That's what solved the lack of parallax in my case anyway.

arzitmahajan commented 2 years ago

How resolved it?