React Component在同级组件之间传递数据时会无限渲染



我的组件结构就像这个

应用程序
|-TopHeader
|-Main
||-线程
|-Modal

Topheader包含一个用于打开带有文本框的Modal的按钮。我正在传递来自Modal的文本框数据->App和更改newPost值,以便Main可以在检测到更改时重新渲染。但这在某种程度上导致了无限的重新渲染。这是我的代码。App:

import "./scss/App.scss";
import Sidebar from "./components/Sidebar";
import TopHeader from "./components/TopHeader";
import Main from "./components/Main";
import RightPan from "./components/RightPan";
import Modal from "./components/Modal";
import React, { useEffect, useState } from "react";
function App() {
const [shouldModalPopUp, setShouldModalPopUp] = useState(false);
const [newPost, setNewPost] = useState();
function handleNewThreadButtonClick() {
setShouldModalPopUp(true);
}
function handleCloseButtonClick() {
setShouldModalPopUp(false);
}
function onPostSubmitHandler(newPost) {
console.log("before preventDefault");
setNewPost(newPost);
handleCloseButtonClick();
}
return (
<div className="App">
{/* <Sidebar key={1} /> */}
<TopHeader
newThreadButtonClickHandler={handleNewThreadButtonClick}
key={2}
/>
<Main newPost={newPost} key={3} />
{/* <RightPan key={4} /> */}
<Modal
shouldModalPopUp={shouldModalPopUp}
handleCloseButtonClick={handleCloseButtonClick}
onPostSubmitHandler={onPostSubmitHandler}
key={5}
/>
</div>
);
}
export default App;

Main

import "../scss/App.scss";
import Thread from "./Thread";
import React, { useEffect, useState } from "react";
function Main(props) {
const [allThreads, setAllThreads] = useState([]);
function onPostSubmitHandler(newPost) {
setAllThreads((prevState) => {
const newList = [];
for (let i = 0; i < prevState.length; i++) {
newList.push(prevState[i]);
}
newList.push({ post: newPost, id: Math.random() });
console.log("previous state length: " + prevState.length);
console.log("new state length: " + newList.length);
return newList;
});
}
console.log("props received in Main" + JSON.stringify(props));
function onDeleteHandler(id) {
console.log("inside ondeletehandler " + id);
const newList = [];
for (let i = 0; i < allThreads.length; i++) {
if (allThreads[i].id != id) {
newList.push(allThreads[i]);
}
}
setAllThreads(newList);
}
if (props.newPost) {
onPostSubmitHandler(props.newPost);
}
return (
<div className="main">
<span>main</span>
{allThreads.map((thread) => {
console.log("appending posts in list");
console.log(thread.post);
return (
<Thread
post={thread.post}
id={thread.id}
onDeleteThread={onDeleteHandler}
/>
);
})}
</div>
);
}
export default Main;

Modal

import React, { useState } from "react";
function Modal(props) {
const [post, setPost] = useState("");
function submitHandler(event) {
event.preventDefault();
props.onPostSubmitHandler(post);
}
function onChangeHandler(event) {
event.preventDefault();
setPost(event.target.value);
}
if (props.shouldModalPopUp) {
return (
<div>
<div className="backdrop" />
<div className="modal">
<form onSubmit={submitHandler}>
<textarea
id="txtArea"
className="postTextArea"
placeholder="please type your post.."
rows="20"
cols="80"
onChange={onChangeHandler}
/>
<br />
<br />
<button
type="button"
className="button"
onClick={props.handleCloseButtonClick}
>
close
</button>
<button type="submit" className="button">
Submit
</button>
</form>
</div>
</div>
);
}
return null;
}
export default Modal;

TopHeader

import "../scss/App.scss";
function TopHeader(props) {
return (
<div className="topHeader">
<button
className="button button--newthread"
onClick={props.newThreadButtonClickHandler}
>
Start a new Thread
</button>
</div>
);
}
export default TopHeader;

Thread

import { useState } from "react/cjs/react.development";
import "../scss/App.scss";
function Thread(props) {
const [post, setPost] = useState(props.post);
const [id, setId] = useState(props.id);
console.log("reached thread method");
const [isDeleted, setIsDeleted] = useState(false);
function deleteHandler() {
setIsDeleted(true);
props.onDeleteThread(id);
}
return (
<div className="thread">
{post}
<button className="button" onClick={deleteHandler}>
delete
</button>
</div>
);
}
export default Thread;

Main:中

if (props.newPost) {
onPostSubmitHandler(props.newPost);
}

在设置newPost并将其作为道具传递给该组件后,该if块将始终返回true

因此,每当Main组件重新渲染时(即,当组件的道具/状态发生变化时,在这种情况下为newPost(,都将执行方法onPostSubmitHandler

此外,在该方法onPostSubmitHandler的第一行中安排了一个状态更改,这将导致无限的重新渲染。

您应该使用useEffect挂钩而不是if检查,并且您的props.newPost变量在依赖项列表中。

您可以使用对象析构函数来获取newPost变量,然后将其传递到依赖数组中,如下所示:

const { newPost } = props;
useEffect(() => {
onPostSubmitHandler(newPost);
}, [newPost]);

最新更新