Question: React/NextJS Timer-based fade in/fade out of text not working

I'm relatively new to React and NextJS. I've spent a good 8 hours and a fair amount of research trying to figure this out with no luck!
I'm trying to set up a component that picks a word at random from an array, fades this in, then after a delay fades it out and fades in a new word.
After hacking together several of my own failed solutions, I found a tutorial and tried their code (with some changes to shift it from TS to JS) but it still doesn't work.
I can get the text to change on a timer easily enough, but not the fading.
Any ideas?
Using NextJS 13, built on StackBlitz's basic NextJS setup
index.js
import { useEffect, useState } from 'react';
import styles from './index.module.css';

const FADE_INTERVAL_MS = 2000;
const WORD_CHANGE_INTERVAL_MS = FADE_INTERVAL_MS * 2;
const WORDS_TO_ANIMATE = [
  'Hello',
  'Ciao',
  'Jambo',
  'Bonjour',
  'Salut',
  'Hola',
  'Nǐ hǎo',
  'Hallo',
  'Hej',
  '👋🏻',
];

export default function AnimatedText() {
  const [fadeProp, setFadeProp] = useState('fadeout');
  const [wordOrder, setWordOrder] = useState(0);

  useEffect(() => {
    const fadeTimeout = setInterval(() => {
      fadeProp === 'fadein' ? setFadeProp('fadeout') : setFadeProp('fadein');
    }, FADE_INTERVAL_MS);

    return () => clearInterval(fadeTimeout);
  }, [fadeProp]);

  useEffect(() => {
    const wordTimeout = setInterval(() => {
      setWordOrder(
        (prevWordOrder) => (prevWordOrder + 1) % WORDS_TO_ANIMATE.length
      );
    }, WORD_CHANGE_INTERVAL_MS);

    return () => clearInterval(wordTimeout);
  }, []);

  return (
    <h2 className={styles.white}>
      <span className={`styles.${fadeProp}`}>
        {WORDS_TO_ANIMATE[wordOrder]}
      </span>
      , I'm bleh.
    </h2>
  );
}


index.module.css
.fadein {
  animation: fadein 0.3s;
  -moz-animation: fadein 0.3s;
  -webkit-animation: fadein 0.3s;
  -o-animation: fadein 0.3s;
}

.fadein {
  animation: fadeout 0.3s;
  -moz-animation: fadeout 0.3s;
  -webkit-animation: fadeout 0.3s;
  -o-animation: fadeout 0.3s;
}

.white {
  color: silver;
}

@keyframes fadein {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes fadeout {
  0% {
    opacity: 1;
    color: blue;
  }
  100% {
    opacity: 0;
    color: red;
  }
}




Answer:
You are in the right path. But you need to fix a few things. Instead of doing:
 <span className={`styles.${fadeProp}`}>
      {WORDS_TO_ANIMATE[wordOrder]}
 </span>

Try it with
 <span className={fadeProp}>
      {WORDS_TO_ANIMATE[wordOrder]}
 </span>

The reason being is that you were not setting your css class name selector correclty. I think after that you can tweak it for you convenience.
------ EDIT -----
Also, you will need to create a .css file, not .module.css. I think the reason  is because the .module.css are compiled and cannot be dynamic.
Create a global.css file inside styles dir. Import it in you _app.js entrypoint inside pages dir.
If you do not have it, it looks something like this:
_app.js
import '../styles/globals.css';
 
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}


Using globals.css is not the best option but you can imrove that later on. Please find more info about styling Nextjs apps here.