I would like to use a setInterval
to cycle which <li>
object has a className
of "showing", like this simple slideshow . I don't know how to do this in React-land.
function NumberList() {
const numbers = [1, 2, 3, 4, 5];
return (
<ul>
{
numbers.map((number) =>
<li key={number.toString()}>{number}</li>
)
}
</ul>
);
}
ReactDOM.render(
<NumberList />,
document.getElementById('root')
);
Anybody have any ideas?
Here's a working demo. Basically, you need to start a timer and keep the current showing list item in the state. The timer will increment the current number every 500ms and wrap around when it exceeds the number of items.
Some things to take note of:
Use the alternative signature of this.setState
because setState
is not guaranteed to be synchronous and if you refer to this.state
within setState
it might be outdated.
Remember to clear the timer upon unmount of the component.
class App extends React.Component { constructor(props) { super(props); this.numbers = [1, 2, 3, 4, 5]; this.state = { current: 0, }; } componentDidMount() { this.timerId = setInterval(() => { this.setState(state => ({ ...state, current: (state.current + 1) % this.numbers.length, })); }, 500); } componentWillUnmount() { clearInterval(this.timerId); } render() { return ( <div className="App"> <ul> {this.numbers.map((number, index) => ( <li key={number} className={index === this.state.current ? 'slide showing' : 'slide'} > {number} </li> ))} </ul> </div> ); } } ReactDOM.render( <App />, document.getElementById('root') );
.slide { font-size: 40px; padding: 40px; box-sizing: border-box; background: #333; color: #fff; display: none; width: 100%; height: 40px; } .slide.showing { display: inherit; } .slide:nth-of-type(1){ background: red; } .slide:nth-of-type(2){ background: orange; } .slide:nth-of-type(3){ background: green; } .slide:nth-of-type(4){ background: blue; } .slide:nth-of-type(5){ background: purple; }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"><div>
You will probably need to use componentDidMount
function to use the setInterval
function so you have access to the classes. Also use ref
to get the hold of the element itself.
https://reactjs.org/docs/refs-and-the-dom.html#when-to-use-refs
Within the componentDidMount
get access to the element and then you should be able to any JS stuff.
demo: https://codesandbox.io/s/oopj96pv65
import React from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import "./style.css";
class App extends React.Component {
componentDidMount() {
var slides = this.elem.children;
var currentSlide = 0;
setInterval(() => {
slides[currentSlide].classList.remove("showing");
currentSlide = (currentSlide + 1) % slides.length;
slides[currentSlide].classList.add("showing");
}, 2000);
}
render() {
return (
<ul
id="slides"
ref={elem => {
this.elem = elem;
}}
>
<li className="slide showing">Slide 1</li>
<li className="slide">Slide 2</li>
<li className="slide">Slide 3</li>
<li className="slide">Slide 4</li>
<li className="slide">Slide 5</li>
</ul>
);
}
}
render(<App />, document.getElementById("root"));
Building on your simple example:
// Store the state outside of the components
const numbers = [1, 2, 3, 4, 5];
let activeNumber = 0;
// A stateless NumberList component takes the numbers and activeNumber props
function NumberList(props) {
// The `active` class is conditionally added to the appropriate `li`
return (
<ul>
{
props.numbers.map((number) =>
<li key={number} className={props.activeNumber === number ? 'active' : ''}>
{number}
</li>
)
}
</ul>
);
}
// Render method takes in the active number
function render(activeNumber) {
ReactDOM.render(
<NumberList numbers={numbers} activeNumber={activeNumber} />,
document.getElementById('root')
);
}
// We set an interval timer to update activeNumber and re-render
setInterval(function() {
if (activeNumber < numbers.length) {
activeNumber++
} else {
activeNumber = 1;
}
render(activeNumber);
}, 1000);
render(); // Initial render
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.