Squish
Squish

Reputation: 457

MaterialUI text fade with useEffect and setInterval

I am using MaterialUI's Fade component to simulate a text carousel that comes in and out according to the provided array in a prop called dataArray. I am using setIntervals to keep switching the boolean of the Fade and to change the array info. The main problem is that the text switches mid transition after the first iteration of the fade. What I am trying to achieve is a smooth fade transition and info switching loop according to the provided array while the text is hidden. I tried using async, but that does not seem to work on setIntevals.

Here is my component:

import React, { useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { Paper, Fade } from '@material-ui/core';
import './FadeCarousel.css';

const useStyles = makeStyles((theme) => ({
  root: {
    backgroundColor: 'black',
  },
  paper: {
    margin: theme.spacing(1),
    backgroundColor: 'rgba(0,0,0,0)',
    color: '#f4dfc0',
    padding: '1vw 0vw 1vw 0vw',
    fontFamily: 'Chenier',
    fontSize: '2vw',
  },
}));

const FadeCarousel = ({ dataArray }) => {
  const classes = useStyles();
  const [checked, setChecked] = React.useState(true);
  const [carouselData, setCarousel] = React.useState(dataArray[0]);

  useEffect(() => {
    var count = 0;
    // Interval Fade
    setInterval(() => {
      setChecked((prev) => !prev);
    }, 5000);
    // Interval Change Data
    setInterval(() => {
      if (count == dataArray.length - 1) {
        count = 0;
      } else count++;
      setCarousel(dataArray[count]);
    }, 8000);
  }, []);

  return (
    <div className={classes.root}>
      <Fade
        in={checked}
        timeout={{
          enter: 3000,
          exit: 3000,
        }}
      >
        <Paper elevation={4} className={classes.paper}>
          {carouselData}
        </Paper>
      </Fade>
    </div>
  );
};

export default FadeCarousel;

Upvotes: 0

Views: 1501

Answers (1)

ckesplin
ckesplin

Reputation: 1793

Your count should change after the Fade goes through its exit cycles to have it change at the moment that the fade is on its "dark" phase.

That means that your timings should be as follows:

intervalFade = X

intervalChangeData = 2*X

Fade timeout = {enter: 2*X, exit: 2*X}

Example here

Code result:

import React, { useEffect } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { Paper, Fade } from '@material-ui/core';

const useStyles = makeStyles((theme) => ({
  root: {
    backgroundColor: 'black',
  },
  paper: {
    margin: theme.spacing(1),
    backgroundColor: 'rgba(0,0,0,0)',
    color: '#f4dfc0',
    padding: '1vw 0vw 1vw 0vw',
    fontFamily: 'Chenier',
    fontSize: '2vw',
  },
}));

const FadeCarousel = ({ dataArray }) => {
  const classes = useStyles();
  const [checked, setChecked] = React.useState(true);
  const [carouselData, setCarousel] = React.useState(dataArray[0]);

  const fadeTime = 1000

  useEffect(() => {
    var count = 0;
    // Interval Fade
    setInterval(() => {
      setChecked((prev) => !prev);
    }, fadeTime);
    // Interval Change Data
    setInterval(() => {
      if (count == dataArray.length - 1) {
        count = 0;
      } else count++;
      setCarousel(dataArray[count]);
    }, fadeTime*2);
  }, []);

  return (
    <div className={classes.root}>
      <Fade
        in={checked}
        timeout={{
          enter: fadeTime*2,
          exit: fadeTime*2,
        }}
      >
        <Paper elevation={4} className={classes.paper}>
          {carouselData}
        </Paper>
      </Fade>
    </div>
  );
};

export default FadeCarousel;

Upvotes: 2

Related Questions