在 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>
);
}
更新:现在可以动态更改文本
我已经 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
orcomponentDidUpdate
. 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>
);
}
更新:现在可以动态更改文本