бегущая строка с обновлением react

Есть задача реализовать закольцованную бегущую строку в компоненте React. Что есть:

Компонент:

const Ticker = (props) => {
  const [currentText, setCurrentText] = useState('');
  const [currentIndex, setCurrentIndex] = useState(0);
  
  useEffect(() => {
    if (props.text.length > props.width) {
      if (currentIndex < props.text.length) {
        const timeout = setTimeout(() => {
          setCurrentIndex(prevIndex => prevIndex + 1);
          setCurrentText(cycleLoopedText(props.text, props.width, currentIndex));
        }, props.delay);
    
        return () => clearTimeout(timeout);

      } else { // to next loop
          setCurrentIndex(0);
          setCurrentText('');
      }
    } else {
      setCurrentText(props.text);
    }
  }, [currentIndex, props.text, props.delay, props.width]);

  return (
    <div>{currentText}</div>
  );  
}

и функция для <Ticker />, которая возвращает часть строки, с учетом закольцованности:

function cycleLoopedText(text, width, index) {
// функция выводит окно в width символов, строка - как кольцо
// если width вышло за пределы text.length, дописывает символы с начала строки
  let result = "";

  if (index < text.length - width) {
    result = text.slice(index, index+width);
  } else if (index < text.length) {  // если окно заканчивается "за строкой"
    result = text.slice(index, text.length);
    result += text.slice(0, index + width - text.length);    
  }

  return result;
}

Соответственно, использование компонента:

<Ticker text={`длинная-длинная-длинная-длинная-длинная строка`} width={19} delay= {167}/>

Теперь вопрос: как сделать, чтобы при изменении text, строка начала отображаться с первого символа. Т.е. если изменился props.text, то setCurrentIndex(0);

PS: Ну, или при использовании <Marquee /> тот же вопрос: как сделать отображение нового текста сначала? И этот компонент не кольцует, а по достижении конца строки начинает ее отображать сначала.


Ответы (1 шт):

Автор решения: ksa

Теперь вопрос: как сделать, чтобы при изменении text, строка начала отображаться с первого символа.

Предложу такой вариант...

//
const Ticker = ({txt, w}) => {
  const [val, setVal] = React.useState(txt)
  React.useEffect(_ => {
    setVal(txt)
    const t = setInterval(_ => {
      setVal(v => v.slice(1, v.lenght) + v[0])
    }, 100)
    return _ => clearInterval(t)
  }, [txt, w])
  const s = val.slice(w - 1)
  return <p>{s}</p>
}
//
const App = props => {
  const txt = 'Теперь вопрос: как сделать, чтобы при изменении text, строка начала отображаться с первого символа. Т.е. если изменился props.text, то setCurrentIndex(0);'
  const w = 100
  return <section>
    <Ticker txt={txt} w={w} />
  </section>
}

const domContainer = document.querySelector('#like_button_container');
const root = ReactDOM.createRoot(domContainer);
root.render(<App />);
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<div id="like_button_container"></div>

→ Ссылка