在 React 中访问动态创建的一组元素

Accessing a dynamically created set of elements in react

我已经 this 直接使用 JS,我正试图通过将其转换为 React 在 Gatsby 网站上实现同样的事情。基本上,重点是让字母以随机顺序出现,但出现在适当的位置。

我卡住的地方(我对 React 还很陌生)是如何以随机顺序创建和访问元素集(跨度),以便能够让它们按该顺序显示.

class about extends Component {

    constructor(props) {
        super(props);
        this.state = {
            aboutText: "This is a test of the emergency broadcast system",
            aboutElements: []
        }
    }
    
    shuffleArray(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }

    render() {

        const arrLetters = this.state.aboutText.split("");
        let arrNumbers = Array.from(Array(arrLetters.length).keys());
        arrNumbers = this.shuffleArray(arrNumbers);
        const arrSpans = arrLetters.map((letter, index) => <span key={index} id={"letter" + index}>{letter}</span>);
        console.log(arrSpans)

this.setState({ aboutElements: arrSpans })

        arrNumbers.forEach(function(item, index) {
            let targetSpan = arrSpans.filter( el => el.key == item);
// NEED TO MAKE THE LETTER VISIBLE HERE
 
        });


        return (
        <section id="about" className={styles.about}>
            <div className="container">
                <p>{ this.state.aboutElements }</p>
            </div>
        </section>
    )
    }
    
}

export default about

所以我正在创建字母数组,将其转换为元素数组,但是当我尝试将其置于某个状态时,出现此错误:

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

我做错了什么?

问题是您在 render 方法中调用 this.setState({ aboutElements: arrSpans })。每次状态改变时都会调用 render 函数所以蛇在这里咬了它的尾巴,创建了一个无限循环 render -> setState -> render -> setState -> ...

但好消息是您可以只使用局部变量来渲染元素,而无需使用状态:

render() {

        const arrLetters = this.state.aboutText.split("");

        const arrSpans = arrLetters.map((letter, index) => <span key={index} id={"letter" + index}>{letter}</span>);
        console.log(arrSpans)

// this.setState({ aboutElements: arrSpans }) // <- not needed


        return (
        <section id="about" className={styles.about}>
            <div className="container">
                <p>{ arrSpans }</p>
            </div>
        </section>
    )
    }

我不确定你打算用 arrNumbers 做什么,但我想你可以自己解决这个问题,因为你知道你可以只使用局部变量

更新:

我只是快速勾画了想要的效果 here

这是代码的副本:

import React, { useEffect, useState, useRef } from "react";

export default function AnimatedLetters({ text }) {
  const interval = useRef();
  const [elements, setElements] = useState([]);
  useEffect(() => {
    let count = 0;
    if (interval.current) {
      clearInterval(interval.current);
    }
    const indices = shuffleArray(
      Array.from({ length: text.length }, (_, i) => i)
    );
    interval.current = setInterval(() => {
      ++count;
      const chars = text.split("").map((char, i) => (
        <span key={i} style={{ opacity: indices[i] < count ? 1 : 0 }}>
          {char}
        </span>
      ));

      setElements(chars);
      if (count > text.length) {
        clearInterval(interval.current);
      }
    }, 100);
  }, [text]);
  return <p>{elements}</p>;
}

function shuffleArray(array) {
  for (var i = array.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}

用法示例:

export default function App() {
  const [text, setText] = useState("Hello Codesandbox");
  return (
    <div className="App">
      <AnimatedLetters text={text} />
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
      />
    </div>
  );
}

更新:现在可以动态更改文本