未捕获错误:太多的重新渲染.React限制了渲染的次数,以防止无限循环.在我的MERN待办事项应用程序使用Vite Re



我试图使MERN待办事项列表应用程序,我的文件夹结构是:1主文件夹中,我有api(后端)和客户端(前端)文件夹。在api: server.js &models文件夹,其中我有todo.js, mongo schema。在客户端:常规的Vite react应用程序结构。

我希望在我的待办事项表上执行crud操作…我试着调试,但不能弄清楚…由于考试,我从开发中休息了很长时间!这是我的App.js:

import React, { useState, useEffect } from "react";
const API_BASE = "http://localhost:3001";
function App() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodos] = useState("");
const [popupActive, setPopupActive] = useState(false);
useEffect(() => {
getTodos();
}, []);
const getTodos = () => {
fetch(API_BASE + "/todos")
.then((res) => res.json())
.then((data) => setTodos(data))
.catch((err) => console.error("Error: ", err));
};
const completeTodo = async (id) => {
const data = await fetch(API_BASE + "/todo/complete" + id).then((res) =>
res.json()
);
setTodos((todos) =>
todos.map((todo) => {
if (todo.id === data._id) {
todo.complete = data.complete;
}
return todo;
})
);
};
const deleteTodo = async (id) => {
const data = await fetch(API_BASE + "todo.delete/" + id, {
method: "DELETE",
}).then((res) => res.json());
setTodos((todos) => todos.filter(todo._id !== data._id));
};
const addTodo = async () => {
const data = await fetch(API_BASE + "/todo/new", {
method: "POST",
headers: {
"content-Type": "application/json",
},
body: JSON.stringify({
text: newTodo,
}),
}).then((res) => res.json());
setTodos([...todos, data]);
setPopupActive(false);
setNewTodos("");
};
return (
<>
<div className="app">
<h1>Welcome, mj...</h1>
<h4>Your Tasks...</h4>
<div className="todos">
{todos.map((todo) => (
<div
className={"todo " + (todo.complete ? "is-complete" : "")}
key={todo._id}
onClick={completeTodo(todo._id)}
>
<div className="checkbox"></div>
<div className="text">{todo.text}</div>
<div className="delete-todo" onClick={deleteTodo(todo._id)}>
x
</div>
</div>
))}
</div>
<div className="addPopup" onClick={setPopupActive(true)}>
+
</div>
{popupActive ? (
<div className="popup">
<div className="closePopup" onClick={setPopupActive(false)}>
X
</div>
<div className="content">
<h3> Add todo...</h3>
<input
type="text"
className="add-todo-input"
onChange={(e) => setNewTodo(e.target.value)}
value={newTodo}
/>
<div className="button" onClick={addTodo}>
Create Task...
</div>
</div>
</div>
) : (
""
)}
</div>
</>
);
}
export default App;

你是在useEffect钩子中使用setState,这会产生一个无限循环。

如果你在一个效果中更新你的状态,你必须为函数的运行添加一个条件,否则你将创建一个无限循环。

任何时候你的状态更新,它使页面渲染,所以如果你不为它设置一个条件-它会重新渲染dom和效果将再次开始运行,它会再次更新你的状态,这将导致一个无限循环。

这里有一个例子:

const Example = () => {

const [state,setState] = useState([])

useEffect(() => {
const fetchFakeData = () => {
if (state.length < 1) {
fetch("https://fakeData.com")
.then((response) => response.json())
.then((data) => {
setState({ data });
});
}
};
fetchFakeData();
}, []);


return <></>
}

Codesandbox例子