简体   繁体   English

如何在React中的孩子上循环className

[英]How to cycle className over children in React

I would like to use a setInterval to cycle which <li> object has a className of "showing", like this simple slideshow . 我想使用setInterval循环哪个<li>对象的className为“ showing”,就像这个简单的slideshow一样 I don't know how to do this in React-land. 我不知道如何在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. 计时器将每500ms递增当前数字,并在超过项目数时回绕。

Some things to take note of: 需要注意的一些事情:

  1. 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. 使用this.setState的替代签名,因为不能保证setState是同步的,并且如果在setState引用this.state ,则它可能已过时。

  2. 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. 您可能需要使用componentDidMount函数才能使用setInterval函数,以便可以访问这些类。 Also use ref to get the hold of the element itself. 也可以使用ref来获取元素本身的所有权。

https://reactjs.org/docs/refs-and-the-dom.html#when-to-use-refs 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. componentDidMount可以访问该元素,然后您应该可以使用任何JS东西。

demo: https://codesandbox.io/s/oopj96pv65 演示: 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM