状态变量更改导致无限渲染循环
我正在尝试使用 React 创建评论部分。该组件使用外连接提取一个大型数据集中的所有评论并回复每个评论,然后将结果复制到两个单独的数组(评论数组和回复数组)中。
但是,当我尝试将评论数组设置为一种状态时变量使组件无限地重新渲染自身。
我已经在出现问题的地方添加了评论。取消注释下面的行会导致程序正常运行,但地图功能没有任何显示
import React, {useState, useEffect} from 'react'
import Axios from 'axios';
import {Form, Button} from 'react-bootstrap';
import Comment from './Comment';
import { render } from 'react-dom';
function Thread(props) {
const {threadID} = props;
const [commentBody, setCommentBody] = useState('');
const [replyArray, setReplyArray] = useState([]);
const [commentArray, setCommentArray] = useState([]);
const [comments, setComments] = useState([]);
let commentResponse = [];
useEffect(() => {
Axios.get(`http://localhost:3001/api/selectcomments/${threadID}`).then((res) => {
commentResponse = res.data;
});
}, [threadID]);
let tempReplies = [];
let tempComments = [];
for(let i = 0 ; i < commentResponse.length; i++)
{
tempComments.push({body: comments[i].body, commentID: comments[i].commentID})
tempReplies.push({replyBody: comments[i].replyBody, commentID: comments[i].commentID})
}
let filteredArray = [...new Map(tempComments.map(x => [x['commentID'], x])).values()]
console.log("splitArray called")
//CAUSES INFINITE RENDER LOOP
setCommentArray(filteredArray);
return (
<section className="comment-wrapper">
<div className="comment-section">
<h2>Comments</h2>
<Form>
<Form.Control
as="textarea"
rows={3}
placeholder="Leave a Comment"
onChange={(val) => {
setCommentBody(val);
}}
/>
</Form>
<Button
// all elements in the comment section have a default margin of 1rem, but this looks strange when applied to this button
style={{ "margin-top": "0rem" }}
type="submit"
variant="primary"
>
Post
</Button>
{
commentArray.map((data) => {
console.log('map function for thread fired');
console.log(commentArray)
const {commentID, body} = data;
const replies = replyArray.filter(x => x.commentID == commentID)
return (
<>
<Comment username="User1" body={body} commentId = {commentID}/>
{
replies.map((replyData)=>{
if(!(replyData.replyBody == null))
{
return(
<div className="reply">
<h3>Username</h3>
<p>{replyData.replyBody}</p>
</div>
)
}
}
)}
</>
);
})}
</div>
</section>
) }
导出默认线程
I'm attemptign to create a comment section using react. The component pulls all of the comments and replies to each comment in one large dataset using an outer join, then it copies the results into two seperate arrays (comment array and replies array)
However, when I try to set the comment array to a state variable the component infinitely re-renders itself.
I've included a comment where the problem occurs. Un-commenting the line below it causes the program to work normally, but the map function has nothing to display
import React, {useState, useEffect} from 'react'
import Axios from 'axios';
import {Form, Button} from 'react-bootstrap';
import Comment from './Comment';
import { render } from 'react-dom';
function Thread(props) {
const {threadID} = props;
const [commentBody, setCommentBody] = useState('');
const [replyArray, setReplyArray] = useState([]);
const [commentArray, setCommentArray] = useState([]);
const [comments, setComments] = useState([]);
let commentResponse = [];
useEffect(() => {
Axios.get(`http://localhost:3001/api/selectcomments/${threadID}`).then((res) => {
commentResponse = res.data;
});
}, [threadID]);
let tempReplies = [];
let tempComments = [];
for(let i = 0 ; i < commentResponse.length; i++)
{
tempComments.push({body: comments[i].body, commentID: comments[i].commentID})
tempReplies.push({replyBody: comments[i].replyBody, commentID: comments[i].commentID})
}
let filteredArray = [...new Map(tempComments.map(x => [x['commentID'], x])).values()]
console.log("splitArray called")
//CAUSES INFINITE RENDER LOOP
setCommentArray(filteredArray);
return (
<section className="comment-wrapper">
<div className="comment-section">
<h2>Comments</h2>
<Form>
<Form.Control
as="textarea"
rows={3}
placeholder="Leave a Comment"
onChange={(val) => {
setCommentBody(val);
}}
/>
</Form>
<Button
// all elements in the comment section have a default margin of 1rem, but this looks strange when applied to this button
style={{ "margin-top": "0rem" }}
type="submit"
variant="primary"
>
Post
</Button>
{
commentArray.map((data) => {
console.log('map function for thread fired');
console.log(commentArray)
const {commentID, body} = data;
const replies = replyArray.filter(x => x.commentID == commentID)
return (
<>
<Comment username="User1" body={body} commentId = {commentID}/>
{
replies.map((replyData)=>{
if(!(replyData.replyBody == null))
{
return(
<div className="reply">
<h3>Username</h3>
<p>{replyData.replyBody}</p>
</div>
)
}
}
)}
</>
);
})}
</div>
</section>
)
}
export default Thread
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你遇到了一个问题,因为每次组件重新渲染时你都会无条件地设置状态;导致再次重新渲染。
在这种情况下,您需要退一步思考何时您实际上需要 UI 自行重绘。在这种情况下,就目前的代码而言,它非常简单 - 当一些数据从服务器 API 返回时。
您已经在
useEffect
中的Axios.get
调用的then()
中运行了一些东西。这里实际上是在设置状态之前进行所有数组切片和切块的理想位置,这将导致重新绘制:You've got an issue because you're unconditionally setting state every time your component re-renders; resulting in yet-another re-render.
In situations like this you need to step back and think about when you actually need your UI to redraw itself. In this case with the code as it stands, it's very simple - when some data has come back from the server API.
You've already got something running in the
then()
of theAxios.get
call in youruseEffect
. Here is actually the ideal place to do all the array slicing-and-dicing before setting the state, which will cause the re-draw: