бегущая строка с обновлением 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 шт):
Теперь вопрос: как сделать, чтобы при изменении 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>