1

I have two issues.

  1. Onload, the bottom links should render only once, but they are rendered twice.
  2. When clicking the box links at the bottom, the current links should smoothly fade out and the new ones fade in. Instead, the new ones initially fade in stacked with the previous ones.

enter image description here

what am I doing wrong here?

Sandbox Link

Relevant animation code:

export default function DynamicScreen({}: IProps) {
  const { screenKey } = useParams()
  const [isLeavingScreen, setIsLeavingScreen] = useState(false)
  const [screen, setScreen] = useState<IDynamicScreen>()
  const [screenLinks, setScreenLinks] = useState<IDynamicScreenLink[]>([])
  const navigate = useNavigate()
  const isFirstRenderRef = useRef(true)

  useEffect(() => {
    if (isFirstRenderRef.current) {
      isFirstRenderRef.current = false
      return
    }
  }, [])

  useEffect(() => {
    const loadScreen = async () => {
      console.log("Screen - Loading")
      const { data: _screen } = await api.getScreen(screenKey!)
      setScreen(_screen)
      setScreenLinks(
        [_screen.link1?.[0], _screen.link2?.[0], _screen.link3?.[0]].filter(
          Boolean,
        ),
      )
      console.log("Screen - Loaded")
    }

    loadScreen()
  }, [screenKey])

  const springApiLory = useSpringRef()
  const springLoryStyle = useSpring({
    from: { opacity: 0, scale: 0 },
    to: { opacity: 1, scale: 1 },
    ref: springApiLory,
  })

  const springApiTitle = useSpringRef()
  const springTitleStyle = useSpring({
    from: { opacity: 0, transform: "translateY(-25px)" },
    to: !isLeavingScreen
      ? { opacity: 1, transform: "translateY(0)" }
      : {
          opacity: 0,
          transform: "translateY(-25px)",
        },

    ref: springApiTitle,
  })

  const springApiScriptHtml = useSpringRef()
  const springScriptHtmlStyle = useSpring({
    from: { opacity: 0, transform: "translateX(-25px)" },
    to: !isLeavingScreen
      ? { opacity: 1, transform: "translateY(0)" }
      : {
          opacity: 0,
          transform: "translateX(-25px)",
        },
    ref: springApiScriptHtml,
  })

  const springApiLinks = useSpringRef()

  const linkTransition = useTransition(isLeavingScreen ? [] : screenLinks, {
    ref: springApiLinks,
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: isLeavingScreen ? { opacity: 0 } : {},
    trail: 100,
  })

  const chain = [
    springApiLory,
    springApiTitle,
    springApiScriptHtml,
    springApiLinks,
  ]

  useChain(
    !isLeavingScreen ? chain : chain.reverse(),
    [...Array(chain.length).keys()].map(calcStaggerDelay),
  )

  const goToLink = (link: string) => {
    setIsLeavingScreen(true)
    setTimeout(() => {
      setScreenLinks([])
      navigate(`/${link}`)

      setIsLeavingScreen(false)
    }, 1000)
  }

  if (!screen) return null

  return (
    <>
      <div className="dynamic-screen-top">
        <div className="left">
          <animated.div style={springTitleStyle}>
            <h1>{screen.title}</h1>
          </animated.div>
          <animated.div style={springScriptHtmlStyle}>
            <div
              dangerouslySetInnerHTML={{
                __html: screen.scriptHtml,
              }}
            />
          </animated.div>

          {/* TODO screen.actions */}
        </div>
        <animated.div style={springLoryStyle} className="right">
          ‍♀️
        </animated.div>
      </div>
      <div className="dynamic-screen-bottom">
        {linkTransition((style, screenLink) => (
          <animated.div
            style={style}
            className="dynamic-screen-bottom-link-wrap"
          >
            <DynamicScreenLink
              linkKey={screenLink!.key}
              onClick={goToLink}
              text={screenLink!.text}
              imageUrl={screenLink!.imageUrl}
              size={screenLink!.size}
            />
          </animated.div>
        ))}
      </div>
    </>
  )
}

interface IProps {}

const calcStaggerDelay = (i: number) => i * 0.1 + 0.1

Shining Love Star
  • 5,734
  • 5
  • 39
  • 49

1 Answers1

0

I don't know if this helps you continue, but what i did first of all is to set screenLinks the to an empty array when navigating to new page

const goToLink = (link: string) => {
    setScreenLinks([]);
    setIsLeavingScreen(true);
    setTimeout(() => {
      navigate(`/${link}`);
      setIsLeavingScreen(false);
    }, 300);
  };

and also, if isLeavingScreen, then set the width to zero, in order for the next screenLinks to take whole space

  const linkTransition = useTransition(isLeavingScreen ? [] : screenLinks, {
    ref: springApiLinks,
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: isLeavingScreen ? { display: "none", width: 0 } : {},
    trail: 100
  });

demo

Apostolos
  • 10,033
  • 5
  • 24
  • 39
  • that might work, but it's a hack, it should work out of the box so I'm pretty sure I'm missing something. Anyway, I ditched react spring in favor of css transitions & animations. – Shining Love Star Jul 17 '22 at 08:55