0

I have wrapper React Component which makes its children fade in from right side and change opacity from 0 to 1, using react-spring and visibility-sensor. Both useEffect and useState make the chidren appear only once after first scroll in.

The problem is that animation shows too fast - there is no transform from 50px from right side to end position. Image/text - the component children just pop up as i scroll in.

Here is the code for this Component:

import React, { useEffect, useState } from 'react';
import { Spring, config } from 'react-spring/renderprops';
import VisibilitySensor from 'react-visibility-sensor';

export const FadeInContainer = ({
 children
}: any) => {
 const [isVisible, setVisibility] = useState(false);
 const [entered, setEntered] = useState(false);

 const onChange = (visiblity: any) => {
  setTimeout(() => {
   setVisibility(visiblity);
  }, 200);
 };

 useEffect(() => {
  if (isVisible) {
   setEntered(true);
  }
 }, [isVisible]);

 const FadeInDirection = () => {
  return (
   <Spring
    delay={500}
    config={config.slow}
    to={{
     opacity: entered ? 1 : 0,
     transform: entered ? 'translateY(0)' : 'translateY(50px)'
    }}
   >
    {({ opacity, transform }) => (
     <div style={{ opacity, transform }}>{children}</div>
    )}
   </Spring>
  );
 };

 return (
  <VisibilitySensor onChange={onChange}>
   <FadeInDirection />
  </VisibilitySensor>
 );
};

What I've tried already: 1. Adding setTimeouts to useEffect, and onChange definition as above. 2. Tried adding scrollDelay for visibility sensor as below:

  <VisibilitySensor onChange={onChange} scrollDelay={300}>

The solution for scrolling only once is from this thread: https://stackoverflow.com/a/58488868

Do you know if something can be done to make animation which happens only once on scroll more smooth (transform mostly)?

1 Answers1

0

I think the problem is, that the animation is not working. It just switches opacity from 0 to 1 without animation. I changed it to the hook based animation and it just worked (only when useSpring was outside the FadeInDirection component). So the initial problem is, that FadeInDirection defined inside FadeInContainer and it has no properties of its own. It was redefined with each render.

Create FadeInDirection as a separate component.

I also eliminated the useEffect, I only set visible when VisibilitySensor onChange return true.

import React, { useState } from "react";
import { useSpring, animated } from "react-spring";
import VisibilitySensor from "react-visibility-sensor";

const FadeInDirection = ({ isVisible, children }) => {
  const props = useSpring({
    opacity: isVisible ? 1 : 0,
    transform: isVisible ? "translateY(0px)" : "translateY(50px)"
  });
  return <animated.div style={props}>{children}</animated.div>;
};

export const FadeInContainer = ({ children }) => {
  const [isVisible, setVisibility] = useState(false);

  const onChange = visiblity => {
    visiblity && setVisibility(visiblity);
  };

  return (
    <VisibilitySensor onChange={onChange}>
      <FadeInDirection isVisible={isVisible}>{children}</FadeInDirection>
    </VisibilitySensor>
  );
};

Here is an example: https://codesandbox.io/s/magical-sun-oqv0v?file=/src/App.js:184-787

Peter Ambruzs
  • 7,763
  • 3
  • 30
  • 36